You can subscribe to this list here.
2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(75) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2009 |
Jan
(70) |
Feb
(20) |
Mar
(52) |
Apr
(149) |
May
(387) |
Jun
(466) |
Jul
(133) |
Aug
(87) |
Sep
(122) |
Oct
(140) |
Nov
(185) |
Dec
(105) |
2010 |
Jan
(85) |
Feb
(45) |
Mar
(75) |
Apr
(17) |
May
(41) |
Jun
(52) |
Jul
(33) |
Aug
(29) |
Sep
(36) |
Oct
(15) |
Nov
(26) |
Dec
(34) |
2011 |
Jan
(26) |
Feb
(25) |
Mar
(26) |
Apr
(29) |
May
(20) |
Jun
(27) |
Jul
(15) |
Aug
(32) |
Sep
(13) |
Oct
(64) |
Nov
(60) |
Dec
(10) |
2012 |
Jan
(64) |
Feb
(63) |
Mar
(39) |
Apr
(43) |
May
(54) |
Jun
(11) |
Jul
(30) |
Aug
(45) |
Sep
(11) |
Oct
(70) |
Nov
(24) |
Dec
(23) |
2013 |
Jan
(17) |
Feb
(8) |
Mar
(35) |
Apr
(40) |
May
(20) |
Jun
(24) |
Jul
(36) |
Aug
(25) |
Sep
(42) |
Oct
(40) |
Nov
(9) |
Dec
(21) |
2014 |
Jan
(29) |
Feb
(24) |
Mar
(60) |
Apr
(22) |
May
(22) |
Jun
(46) |
Jul
(11) |
Aug
(23) |
Sep
(26) |
Oct
(10) |
Nov
(14) |
Dec
(2) |
2015 |
Jan
(28) |
Feb
(47) |
Mar
(33) |
Apr
(58) |
May
(5) |
Jun
(1) |
Jul
|
Aug
(8) |
Sep
(12) |
Oct
(25) |
Nov
(58) |
Dec
(21) |
2016 |
Jan
(12) |
Feb
(40) |
Mar
(2) |
Apr
(1) |
May
(67) |
Jun
(2) |
Jul
(5) |
Aug
(36) |
Sep
|
Oct
(24) |
Nov
(17) |
Dec
(50) |
2017 |
Jan
(14) |
Feb
(16) |
Mar
(2) |
Apr
(35) |
May
(14) |
Jun
(16) |
Jul
(3) |
Aug
(3) |
Sep
|
Oct
(19) |
Nov
|
Dec
(16) |
2018 |
Jan
(55) |
Feb
(11) |
Mar
(34) |
Apr
(14) |
May
(4) |
Jun
(20) |
Jul
(39) |
Aug
(16) |
Sep
(17) |
Oct
(16) |
Nov
(20) |
Dec
(30) |
2019 |
Jan
(29) |
Feb
(24) |
Mar
(37) |
Apr
(26) |
May
(19) |
Jun
(21) |
Jul
(2) |
Aug
(3) |
Sep
(9) |
Oct
(12) |
Nov
(12) |
Dec
(12) |
2020 |
Jan
(47) |
Feb
(36) |
Mar
(54) |
Apr
(44) |
May
(37) |
Jun
(19) |
Jul
(32) |
Aug
(13) |
Sep
(16) |
Oct
(24) |
Nov
(32) |
Dec
(11) |
2021 |
Jan
(14) |
Feb
(5) |
Mar
(40) |
Apr
(32) |
May
(42) |
Jun
(31) |
Jul
(29) |
Aug
(47) |
Sep
(38) |
Oct
(17) |
Nov
(74) |
Dec
(33) |
2022 |
Jan
(11) |
Feb
(15) |
Mar
(40) |
Apr
(21) |
May
(39) |
Jun
(44) |
Jul
(19) |
Aug
(46) |
Sep
(79) |
Oct
(35) |
Nov
(21) |
Dec
(15) |
2023 |
Jan
(56) |
Feb
(13) |
Mar
(43) |
Apr
(28) |
May
(60) |
Jun
(15) |
Jul
(29) |
Aug
(28) |
Sep
(32) |
Oct
(21) |
Nov
(42) |
Dec
(39) |
2024 |
Jan
(35) |
Feb
(17) |
Mar
(28) |
Apr
(7) |
May
(14) |
Jun
(35) |
Jul
(30) |
Aug
(35) |
Sep
(30) |
Oct
(28) |
Nov
(38) |
Dec
(18) |
2025 |
Jan
(21) |
Feb
(28) |
Mar
(36) |
Apr
(35) |
May
(34) |
Jun
(58) |
Jul
(9) |
Aug
(37) |
Sep
|
Oct
|
Nov
|
Dec
|
From: OpenOCD-Gerrit <ope...@us...> - 2020-12-02 23:18:05
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 7b641d3d4e9b0407e5410267459fcbc64f075fde (commit) from d459a2d27df52643dc8932827a63467a14f7c162 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7b641d3d4e9b0407e5410267459fcbc64f075fde Author: Marc Schink <de...@za...> Date: Thu Sep 17 15:23:31 2020 +0200 Add initial RTT support Real Time Transfer (RTT) is an interface specified by SEGGER based on basic memory reads and writes to transfer data bidirectionally between target and host. Every target that supports so called "background memory access", which means that the target memory can be accessed by the debugger while the target is running, can be used. RTT is especially of interest for targets which do not support Serial Wire Output (SWO) (e.g. ARM Cortex-M0) or where using semihosting is not possible (e.g. real-time applications) [1]. The data transfer is organized in channels where each channel consists of an up- and/or down-channel. See [2] for more details. Channels are exposed via TCP connections. One or more RTT server can be assigned to each channel to make them accessible to an unlimited number of TCP connections. The current implementation does not respect buffer flags which are used to determine what happens when writing to a full buffer. Note that the implementation is designed in a way that the RTT operations can be directly performed by an adapter (e.g. J-Link). [1] https://devzone.nordicsemi.com/tutorials/6/ [2] https://www.segger.com/jlink-rtt.html Change-Id: I8bc8a1b381fb74e08b8752d5cf53804cc573c1e0 Signed-off-by: Marc Schink <de...@za...> Reviewed-on: http://openocd.zylin.com/4055 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 65b5d65b2..cc7b6b22e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8423,6 +8423,94 @@ the watchpoint should trigger. The value may be first be masked using @var{mask} to mark ``don't care'' fields. @end deffn + +@section Real Time Transfer (RTT) + +Real Time Transfer (RTT) is an interface specified by SEGGER based on basic +memory reads and writes to transfer data bidirectionally between target and host. +The specification is independent of the target architecture. +Every target that supports so called "background memory access", which means +that the target memory can be accessed by the debugger while the target is +running, can be used. +This interface is especially of interest for targets without +Serial Wire Output (SWO), such as ARM Cortex-M0, or where semihosting is not +applicable because of real-time constraints. + +@quotation Note +The current implementation supports only single target devices. +@end quotation + +The data transfer between host and target device is organized through +unidirectional up/down-channels for target-to-host and host-to-target +communication, respectively. + +@quotation Note +The current implementation does not respect channel buffer flags. +They are used to determine what happens when writing to a full buffer, for +example. +@end quotation + +Channels are exposed via raw TCP/IP connections. One or more RTT servers can be +assigned to each channel to make them accessible to an unlimited number +of TCP/IP connections. + +@deffn Command {rtt setup} address size ID +Configure RTT for the currently selected target. +Once RTT is started, OpenOCD searches for a control block with the +identifier @var{ID} starting at the memory address @var{address} within the next +@var{size} bytes. +@end deffn + +@deffn Command {rtt start} +Start RTT. +If the control block location is not known, OpenOCD starts searching for it. +@end deffn + +@deffn Command {rtt stop} +Stop RTT. +@end deffn + +@deffn Command {rtt polling_interval [interval]} +Display the polling interval. +If @var{interval} is provided, set the polling interval. +The polling interval determines (in milliseconds) how often the up-channels are +checked for new data. +@end deffn + +@deffn Command {rtt channels} +Display a list of all channels and their properties. +@end deffn + +@deffn Command {rtt channellist} +Return a list of all channels and their properties as Tcl list. +The list can be manipulated easily from within scripts. +@end deffn + +@deffn Command {rtt server start} port channel +Start a TCP server on @var{port} for the channel @var{channel}. +@end deffn + +@deffn Command {rtt server stop} port +Stop the TCP sever with port @var{port}. +@end deffn + +The following example shows how to setup RTT using the SEGGER RTT implementation +on the target device. + +@example +resume + +rtt setup 0x20000000 2048 "SEGGER RTT" +rtt start + +rtt server start 9090 0 +@end example + +In this example, OpenOCD searches the control block with the ID "SEGGER RTT" +starting at 0x20000000 for 2048 bytes. The RTT channel 0 is exposed through the +TCP/IP port 9090. + + @section Misc Commands @cindex profiling diff --git a/src/Makefile.am b/src/Makefile.am index 07981aa67..781c1e74f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,7 +53,8 @@ endif %D%/target/libtarget.la \ %D%/server/libserver.la \ %D%/rtos/librtos.la \ - %D%/helper/libhelper.la + %D%/helper/libhelper.la \ + %D%/rtt/librtt.la BIN2C = $(srcdir)/%D%/helper/bin2char.sh @@ -83,3 +84,4 @@ include %D%/rtos/Makefile.am include %D%/server/Makefile.am include %D%/flash/Makefile.am include %D%/pld/Makefile.am +include %D%/rtt/Makefile.am diff --git a/src/openocd.c b/src/openocd.c index 604b36d21..83c35458b 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -38,9 +38,11 @@ #include <pld/pld.h> #include <target/arm_cti.h> #include <target/arm_adi_v5.h> +#include <rtt/rtt.h> #include <server/server.h> #include <server/gdb_server.h> +#include <server/rtt_server.h> #ifdef HAVE_STRINGS_H #include <strings.h> @@ -244,6 +246,7 @@ static struct command_context *setup_command_handler(Jim_Interp *interp) &server_register_commands, &gdb_register_commands, &log_register_commands, + &rtt_server_register_commands, &transport_register_commands, &interface_register_commands, &target_register_commands, @@ -335,6 +338,9 @@ int openocd_main(int argc, char *argv[]) if (ioutil_init(cmd_ctx) != ERROR_OK) return EXIT_FAILURE; + if (rtt_init() != ERROR_OK) + return EXIT_FAILURE; + LOG_OUTPUT("For bug reports, read\n\t" "http://openocd.org/doc/doxygen/bugs.html" "\n"); @@ -364,6 +370,7 @@ int openocd_main(int argc, char *argv[]) /* Shutdown commandline interface */ command_exit(cmd_ctx); + rtt_exit(); free_config(); if (ERROR_FAIL == ret) diff --git a/src/rtt/Makefile.am b/src/rtt/Makefile.am new file mode 100644 index 000000000..e3fcefdbf --- /dev/null +++ b/src/rtt/Makefile.am @@ -0,0 +1,2 @@ +noinst_LTLIBRARIES += %D%/librtt.la +%C%_librtt_la_SOURCES = %D%/rtt.c %D%/rtt.h %D%/tcl.c diff --git a/src/rtt/rtt.c b/src/rtt/rtt.c new file mode 100644 index 000000000..bf3cca51b --- /dev/null +++ b/src/rtt/rtt.c @@ -0,0 +1,332 @@ +/* + * Copyright (C) 2016-2020 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> + +#include <helper/log.h> +#include <helper/list.h> +#include <target/target.h> +#include <target/rtt.h> + +#include "rtt.h" + +static struct { + struct rtt_source source; + /** Control block. */ + struct rtt_control ctrl; + struct target *target; + /** Start address to search for the control block. */ + target_addr_t addr; + /** Size of the control block search area. */ + size_t size; + /** Control block identifier. */ + char id[RTT_CB_MAX_ID_LENGTH]; + /** Whether RTT is configured. */ + bool configured; + /** Whether RTT is started. */ + bool started; + /** Whether configuration changed. */ + bool changed; + /** Whether the control block was found. */ + bool found_cb; + + struct rtt_sink_list **sink_list; + size_t sink_list_length; + + unsigned int polling_interval; +} rtt; + +int rtt_init(void) +{ + rtt.sink_list_length = 1; + rtt.sink_list = calloc(rtt.sink_list_length, + sizeof(struct rtt_sink_list *)); + + if (!rtt.sink_list) + return ERROR_FAIL; + + rtt.sink_list[0] = NULL; + rtt.started = false; + + rtt.polling_interval = 100; + + return ERROR_OK; +} + +int rtt_exit(void) +{ + free(rtt.sink_list); + + return ERROR_OK; +} + +static int read_channel_callback(void *user_data) +{ + int ret; + + ret = rtt.source.read(rtt.target, &rtt.ctrl, rtt.sink_list, + rtt.sink_list_length, NULL); + + if (ret != ERROR_OK) { + target_unregister_timer_callback(&read_channel_callback, NULL); + rtt.source.stop(rtt.target, NULL); + return ret; + } + + return ERROR_OK; +} + +int rtt_setup(target_addr_t address, size_t size, const char *id) +{ + size_t id_length = strlen(id); + + if (!id_length || id_length >= RTT_CB_MAX_ID_LENGTH) { + LOG_ERROR("rtt: Invalid control block ID"); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + rtt.addr = address; + rtt.size = size; + strncpy(rtt.id, id, id_length + 1); + rtt.changed = true; + rtt.configured = true; + + return ERROR_OK; +} + +int rtt_register_source(const struct rtt_source source, + struct target *target) +{ + if (!source.find_cb || !source.read_cb || !source.read_channel_info) + return ERROR_FAIL; + + if (!source.start || !source.stop) + return ERROR_FAIL; + + if (!source.read || !source.write) + return ERROR_FAIL; + + rtt.source = source; + rtt.target = target; + + return ERROR_OK; +} + +int rtt_start(void) +{ + int ret; + target_addr_t addr = rtt.addr; + + if (rtt.started) + return ERROR_OK; + + if (!rtt.found_cb || rtt.changed) { + rtt.source.find_cb(rtt.target, &addr, rtt.size, rtt.id, + &rtt.found_cb, NULL); + + rtt.changed = false; + + if (rtt.found_cb) { + LOG_INFO("rtt: Control block found at 0x%" TARGET_PRIxADDR, + addr); + rtt.ctrl.address = addr; + } else { + LOG_INFO("rtt: No control block found"); + return ERROR_OK; + } + } + + ret = rtt.source.read_cb(rtt.target, rtt.ctrl.address, &rtt.ctrl, NULL); + + if (ret != ERROR_OK) + return ret; + + ret = rtt.source.start(rtt.target, &rtt.ctrl, NULL); + + if (ret != ERROR_OK) + return ret; + + target_register_timer_callback(&read_channel_callback, + rtt.polling_interval, 1, NULL); + rtt.started = true; + + return ERROR_OK; +} + +int rtt_stop(void) +{ + int ret; + + if (!rtt.configured) { + LOG_ERROR("rtt: Not configured"); + return ERROR_FAIL; + } + + target_unregister_timer_callback(&read_channel_callback, NULL); + rtt.started = false; + + ret = rtt.source.stop(rtt.target, NULL); + + if (ret != ERROR_OK) + return ret; + + return ERROR_OK; +} + +static int adjust_sink_list(size_t length) +{ + struct rtt_sink_list **tmp; + + if (length <= rtt.sink_list_length) + return ERROR_OK; + + tmp = realloc(rtt.sink_list, sizeof(struct rtt_sink_list *) * length); + + if (!tmp) + return ERROR_FAIL; + + for (size_t i = rtt.sink_list_length; i < length; i++) + tmp[i] = NULL; + + rtt.sink_list = tmp; + rtt.sink_list_length = length; + + return ERROR_OK; +} + +int rtt_register_sink(unsigned int channel_index, rtt_sink_read read, + void *user_data) +{ + struct rtt_sink_list *tmp; + + if (channel_index >= rtt.sink_list_length) { + if (adjust_sink_list(channel_index + 1) != ERROR_OK) + return ERROR_FAIL; + } + + LOG_DEBUG("rtt: Registering sink for channel %u", channel_index); + + tmp = malloc(sizeof(struct rtt_sink_list)); + + if (!tmp) + return ERROR_FAIL; + + tmp->read = read; + tmp->user_data = user_data; + tmp->next = rtt.sink_list[channel_index]; + + rtt.sink_list[channel_index] = tmp; + + return ERROR_OK; +} + +int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read, + void *user_data) +{ + struct rtt_sink_list *prev_sink; + + LOG_DEBUG("rtt: Unregistering sink for channel %u", channel_index); + + if (channel_index >= rtt.sink_list_length) + return ERROR_FAIL; + + prev_sink = rtt.sink_list[channel_index]; + + for (struct rtt_sink_list *sink = rtt.sink_list[channel_index]; sink; + prev_sink = sink, sink = sink->next) { + if (sink->read == read && sink->user_data == user_data) { + + if (sink == rtt.sink_list[channel_index]) + rtt.sink_list[channel_index] = sink->next; + else + prev_sink->next = sink->next; + + free(sink); + + return ERROR_OK; + } + } + + return ERROR_OK; +} + +int rtt_get_polling_interval(unsigned int *interval) +{ + if (!interval) + return ERROR_FAIL; + + *interval = rtt.polling_interval; + + return ERROR_OK; +} + +int rtt_set_polling_interval(unsigned int interval) +{ + if (!interval) + return ERROR_FAIL; + + if (rtt.polling_interval != interval) { + target_unregister_timer_callback(&read_channel_callback, NULL); + target_register_timer_callback(&read_channel_callback, interval, 1, + NULL); + } + + rtt.polling_interval = interval; + + return ERROR_OK; +} + +int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, + size_t *length) +{ + if (channel_index >= rtt.ctrl.num_up_channels) { + LOG_WARNING("rtt: Down-channel %u is not available", channel_index); + return ERROR_OK; + } + + return rtt.source.write(rtt.target, &rtt.ctrl, channel_index, buffer, + length, NULL); +} + +bool rtt_started(void) +{ + return rtt.started; +} + +bool rtt_configured(void) +{ + return rtt.configured; +} + +bool rtt_found_cb(void) +{ + return rtt.found_cb; +} + +const struct rtt_control *rtt_get_control(void) +{ + return &rtt.ctrl; +} + +int rtt_read_channel_info(unsigned int channel_index, + enum rtt_channel_type type, struct rtt_channel_info *info) +{ + return rtt.source.read_channel_info(rtt.target, &rtt.ctrl, + channel_index, type, info, NULL); +} diff --git a/src/rtt/rtt.h b/src/rtt/rtt.h new file mode 100644 index 000000000..597c83829 --- /dev/null +++ b/src/rtt/rtt.h @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2016-2020 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPENOCD_RTT_RTT_H +#define OPENOCD_RTT_RTT_H + +#include <stdint.h> +#include <stdbool.h> + +#include <helper/command.h> +#include <target/target.h> + +/** + * Control block ID length in bytes, including the trailing null-terminator. + */ +#define RTT_CB_MAX_ID_LENGTH 16 + +/* Control block size in bytes. */ +#define RTT_CB_SIZE (RTT_CB_MAX_ID_LENGTH + 2 * sizeof(uint32_t)) + +/* Channel structure size in bytes. */ +#define RTT_CHANNEL_SIZE 24 + +/* Minimal channel buffer size in bytes. */ +#define RTT_CHANNEL_BUFFER_MIN_SIZE 2 + +/** RTT control block. */ +struct rtt_control { + /** Control block address on the target. */ + target_addr_t address; + /** Control block identifier, including trailing null-terminator. */ + char id[RTT_CB_MAX_ID_LENGTH]; + /** Maximum number of up-channels. */ + uint32_t num_up_channels; + /** Maximum number of down-channels. */ + uint32_t num_down_channels; +}; + +/** RTT channel. */ +struct rtt_channel { + /** Channel structure address on the target. */ + target_addr_t address; + /** Channel name address on the target. */ + uint32_t name_addr; + /** Buffer address on the target. */ + uint32_t buffer_addr; + /** Channel buffer size in bytes. */ + uint32_t size; + /** Write position within the buffer in bytes. */ + uint32_t write_pos; + /** Read position within the buffer in bytes. */ + uint32_t read_pos; + /** + * Buffer flags. + * + * @note: Not used at the moment. + */ + uint32_t flags; +}; + +/** RTT channel information. */ +struct rtt_channel_info { + /** Channel name. */ + char *name; + /** Length of the name in bytes, including the trailing null-terminator. */ + size_t name_length; + /** Buffer size in bytes. */ + uint32_t size; + /** + * Buffer flags. + * + * @note: Not used at the moment. + */ + uint32_t flags; +}; + +typedef int (*rtt_sink_read)(unsigned int channel, const uint8_t *buffer, + size_t length, void *user_data); + +struct rtt_sink_list { + rtt_sink_read read; + void *user_data; + + struct rtt_sink_list *next; +}; + +/** Channel type. */ +enum rtt_channel_type { + /** Up channel (target to host). */ + RTT_CHANNEL_TYPE_UP, + /** Down channel (host to target). */ + RTT_CHANNEL_TYPE_DOWN +}; + +typedef int (*rtt_source_find_ctrl_block)(struct target *target, + target_addr_t *address, size_t size, const char *id, bool *found, + void *user_data); +typedef int (*rtt_source_read_ctrl_block)(struct target *target, + target_addr_t address, struct rtt_control *ctrl_block, + void *user_data); +typedef int (*rtt_source_read_channel_info)(struct target *target, + const struct rtt_control *ctrl, unsigned int channel, + enum rtt_channel_type type, struct rtt_channel_info *info, + void *user_data); +typedef int (*rtt_source_start)(struct target *target, + const struct rtt_control *ctrl, void *user_data); +typedef int (*rtt_source_stop)(struct target *target, void *user_data); +typedef int (*rtt_source_read)(struct target *target, + const struct rtt_control *ctrl, struct rtt_sink_list **sinks, + size_t num_channels, void *user_data); +typedef int (*rtt_source_write)(struct target *target, + struct rtt_control *ctrl, unsigned int channel, + const uint8_t *buffer, size_t *length, void *user_data); + +/** RTT source. */ +struct rtt_source { + rtt_source_find_ctrl_block find_cb; + rtt_source_read_ctrl_block read_cb; + rtt_source_read_channel_info read_channel_info; + rtt_source_start start; + rtt_source_stop stop; + rtt_source_read read; + rtt_source_write write; +}; + +/** + * Initialize Real-Time Transfer (RTT). + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_init(void); + +/** + * Shutdown Real-Time Transfer (RTT). + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_exit(void); + +/** + * Register an RTT source for a target. + * + * @param[in] source RTT source. + * @param[in,out] target Target. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_register_source(const struct rtt_source source, + struct target *target); + +/** + * Setup RTT. + * + * @param[in] address Start address to search for the control block. + * @param[in] size Size of the control block search area. + * @param[in] id Identifier of the control block. Must be null-terminated. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_setup(target_addr_t address, size_t size, const char *id); + +/** + * Start Real-Time Transfer (RTT). + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_start(void); + +/** + * Stop Real-Time Transfer (RTT). + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_stop(void); + +/** + * Get the polling interval. + * + * @param[out] interval Polling interval in milliseconds. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_get_polling_interval(unsigned int *interval); + +/** + * Set the polling interval. + * + * @param[in] interval Polling interval in milliseconds. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_set_polling_interval(unsigned int interval); + +/** + * Get whether RTT is started. + * + * @returns Whether RTT is started. + */ +bool rtt_started(void); + +/** + * Get whether RTT is configured. + * + * @returns Whether RTT is configured. + */ +bool rtt_configured(void); + +/** + * Get whether RTT control block was found. + * + * @returns Whether RTT was found. + */ +bool rtt_found_cb(void); + +/** + * Get the RTT control block. + * + * @returns The RTT control block. + */ +const struct rtt_control *rtt_get_control(void); + +/** + * Read channel information. + * + * @param[in] channel_index Channel index. + * @param[in] channel_type Channel type. + * @param[out] info Channel information. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_read_channel_info(unsigned int channel_index, + enum rtt_channel_type type, struct rtt_channel_info *info); + +/** + * Register an RTT sink. + * + * @param[in] channel_index Channel index. + * @param[in] read Read callback function. + * @param[in,out] user_data User data to be passed to the callback function. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_register_sink(unsigned int channel_index, rtt_sink_read read, + void *user_data); + +/** + * Unregister an RTT sink. + * + * @param[in] channel_index Channel index. + * @param[in] read Read callback function. + * @param[in,out] user_data User data to be passed to the callback function. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_unregister_sink(unsigned int channel_index, rtt_sink_read read, + void *user_data); + +/** + * Write to an RTT channel. + * + * @param[in] channel_index Channel index. + * @param[in] buffer Buffer with data that should be written to the channel. + * @param[in,out] length Number of bytes to write. On success, the argument gets + * updated with the actual number of written bytes. + * + * @returns ERROR_OK on success, an error code on failure. + */ +int rtt_write_channel(unsigned int channel_index, const uint8_t *buffer, + size_t *length); + +extern const struct command_registration rtt_target_command_handlers[]; + +#endif /* OPENOCD_RTT_RTT_H */ diff --git a/src/rtt/tcl.c b/src/rtt/tcl.c new file mode 100644 index 000000000..f5abf2e5e --- /dev/null +++ b/src/rtt/tcl.c @@ -0,0 +1,311 @@ +/* + * Copyright (C) 2019-2020 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <helper/log.h> +#include <target/rtt.h> + +#include "rtt.h" + +#define CHANNEL_NAME_SIZE 128 + +COMMAND_HANDLER(handle_rtt_setup_command) +{ +struct rtt_source source; + + if (CMD_ARGC != 3) + return ERROR_COMMAND_SYNTAX_ERROR; + + source.find_cb = &target_rtt_find_control_block; + source.read_cb = &target_rtt_read_control_block; + source.start = &target_rtt_start; + source.stop = &target_rtt_stop; + source.read = &target_rtt_read_callback; + source.write = &target_rtt_write_callback; + source.read_channel_info = &target_rtt_read_channel_info; + + target_addr_t address; + uint32_t size; + + COMMAND_PARSE_NUMBER(target_addr, CMD_ARGV[0], address); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], size); + + rtt_register_source(source, get_current_target(CMD_CTX)); + + if (rtt_setup(address, size, CMD_ARGV[2]) != ERROR_OK) + return ERROR_FAIL; + + return ERROR_OK; +} + +COMMAND_HANDLER(handle_rtt_start_command) +{ + if (CMD_ARGC > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!rtt_configured()) { + command_print(CMD, "RTT is not configured"); + return ERROR_FAIL; + } + + return rtt_start(); +} + +COMMAND_HANDLER(handle_rtt_stop_command) +{ + if (CMD_ARGC > 0) + return ERROR_COMMAND_SYNTAX_ERROR; + + return rtt_stop(); +} + +COMMAND_HANDLER(handle_rtt_polling_interval_command) +{ + if (CMD_ARGC == 0) { + int ret; + unsigned int interval; + + ret = rtt_get_polling_interval(&interval); + + if (ret != ERROR_OK) { + command_print(CMD, "Failed to get polling interval"); + return ret; + } + + command_print(CMD, "%u ms", interval); + } else if (CMD_ARGC == 1) { + int ret; + unsigned int interval; + + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], interval); + ret = rtt_set_polling_interval(interval); + + if (ret != ERROR_OK) { + command_print(CMD, "Failed to set polling interval"); + return ret; + } + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(handle_rtt_channels_command) +{ + int ret; + char channel_name[CHANNEL_NAME_SIZE]; + const struct rtt_control *ctrl; + struct rtt_channel_info info; + + if (!rtt_found_cb()) { + command_print(CMD, "rtt: Control block not available"); + return ERROR_FAIL; + } + + ctrl = rtt_get_control(); + + command_print(CMD, "Channels: up=%u, down=%u", ctrl->num_up_channels, + ctrl->num_down_channels); + + command_print(CMD, "Up-channels:"); + + info.name = channel_name; + info.name_length = sizeof(channel_name); + + for (unsigned int i = 0; i < ctrl->num_up_channels; i++) { + ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info); + + if (ret != ERROR_OK) + return ret; + + if (!info.size) + continue; + + command_print(CMD, "%u: %s %u %u", i, info.name, info.size, + info.flags); + } + + command_print(CMD, "Down-channels:"); + + for (unsigned int i = 0; i < ctrl->num_down_channels; i++) { + ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info); + + if (ret != ERROR_OK) + return ret; + + if (!info.size) + continue; + + command_print(CMD, "%u: %s %u %u", i, info.name, info.size, + info.flags); + } + + return ERROR_OK; +} + +static int jim_channel_list(Jim_Interp *interp, int argc, + Jim_Obj * const *argv) +{ + Jim_Obj *list; + Jim_Obj *channel_list; + char channel_name[CHANNEL_NAME_SIZE]; + const struct rtt_control *ctrl; + struct rtt_channel_info info; + + if (!rtt_found_cb()) { + Jim_SetResultFormatted(interp, "rtt: Control block not available"); + return ERROR_FAIL; + } + + ctrl = rtt_get_control(); + + info.name = channel_name; + info.name_length = sizeof(channel_name); + + list = Jim_NewListObj(interp, NULL, 0); + channel_list = Jim_NewListObj(interp, NULL, 0); + + for (unsigned int i = 0; i < ctrl->num_up_channels; i++) { + int ret; + Jim_Obj *tmp; + + ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_UP, &info); + + if (ret != ERROR_OK) + return ret; + + if (!info.size) + continue; + + tmp = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "name", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + info.name, -1)); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "size", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp, + info.size)); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "flags", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp, + info.flags)); + + Jim_ListAppendElement(interp, channel_list, tmp); + } + + Jim_ListAppendElement(interp, list, channel_list); + + channel_list = Jim_NewListObj(interp, NULL, 0); + + for (unsigned int i = 0; i < ctrl->num_down_channels; i++) { + int ret; + Jim_Obj *tmp; + + ret = rtt_read_channel_info(i, RTT_CHANNEL_TYPE_DOWN, &info); + + if (ret != ERROR_OK) + return ret; + + if (!info.size) + continue; + + tmp = Jim_NewListObj(interp, NULL, 0); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "name", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + info.name, -1)); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "size", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp, + info.size)); + + Jim_ListAppendElement(interp, tmp, Jim_NewStringObj(interp, + "flags", -1)); + Jim_ListAppendElement(interp, tmp, Jim_NewIntObj(interp, + info.flags)); + + Jim_ListAppendElement(interp, channel_list, tmp); + } + + Jim_ListAppendElement(interp, list, channel_list); + Jim_SetResult(interp, list); + + return JIM_OK; +} + +static const struct command_registration rtt_subcommand_handlers[] = { + { + .name = "setup", + .handler = handle_rtt_setup_command, + .mode = COMMAND_ANY, + .help = "setup RTT", + .usage = "<address> <size> <ID>" + }, + { + .name = "start", + .handler = handle_rtt_start_command, + .mode = COMMAND_EXEC, + .help = "start RTT", + .usage = "" + }, + { + .name = "stop", + .handler = handle_rtt_stop_command, + .mode = COMMAND_EXEC, + .help = "stop RTT", + .usage = "" + }, + { + .name = "polling_interval", + .handler = handle_rtt_polling_interval_command, + .mode = COMMAND_EXEC, + .help = "show or set polling interval in ms", + .usage = "[interval]" + }, + { + .name = "channels", + .handler = handle_rtt_channels_command, + .mode = COMMAND_EXEC, + .help = "list available channels", + .usage = "" + }, + { + .name = "channellist", + .jim_handler = jim_channel_list, + .mode = COMMAND_EXEC, + .help = "list available channels", + .usage = "" + }, + COMMAND_REGISTRATION_DONE +}; + +const struct command_registration rtt_target_command_handlers[] = { + { + .name = "rtt", + .mode = COMMAND_EXEC, + .help = "RTT target commands", + .usage = "", + .chain = rtt_subcommand_handlers + }, + COMMAND_REGISTRATION_DONE +}; diff --git a/src/server/Makefile.am b/src/server/Makefile.am index 804efac16..d270ee281 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -8,7 +8,9 @@ noinst_LTLIBRARIES += %D%/libserver.la %D%/gdb_server.h \ %D%/server_stubs.c \ %D%/tcl_server.c \ - %D%/tcl_server.h + %D%/tcl_server.h \ + %D%/rtt_server.c \ + %D%/rtt_server.h %C%_libserver_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW diff --git a/src/server/rtt_server.c b/src/server/rtt_server.c new file mode 100644 index 000000000..3c885cce0 --- /dev/null +++ b/src/server/rtt_server.c @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2016-2017 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <rtt/rtt.h> + +#include "server.h" +#include "rtt_server.h" + +/** + * @file + * + * RTT server. + * + * This server allows access to Real Time Transfer (RTT) channels via TCP + * connections. + */ + +struct rtt_service { + unsigned int channel; +}; + +static int read_callback(unsigned int channel, const uint8_t *buffer, + size_t length, void *user_data) +{ + int ret; + struct connection *connection; + size_t offset; + + connection = (struct connection *)user_data; + offset = 0; + + while (offset < length) { + ret = connection_write(connection, buffer + offset, length - offset); + + if (ret < 0) { + LOG_ERROR("Failed to write data to socket."); + return ERROR_FAIL; + } + + offset += ret; + } + + return ERROR_OK; +} + +static int rtt_new_connection(struct connection *connection) +{ + int ret; + struct rtt_service *service; + + service = connection->service->priv; + + LOG_DEBUG("rtt: New connection for channel %u", service->channel); + + ret = rtt_register_sink(service->channel, &read_callback, connection); + + if (ret != ERROR_OK) + return ret; + + return ERROR_OK; +} + +static int rtt_connection_closed(struct connection *connection) +{ + struct rtt_service *service; + + service = (struct rtt_service *)connection->service->priv; + rtt_unregister_sink(service->channel, &read_callback, connection); + + LOG_DEBUG("rtt: Connection for channel %u closed", service->channel); + + return ERROR_OK; +} + +static int rtt_input(struct connection *connection) +{ + int bytes_read; + unsigned char buffer[1024]; + struct rtt_service *service; + size_t length; + + service = (struct rtt_service *)connection->service->priv; + bytes_read = connection_read(connection, buffer, sizeof(buffer)); + + if (!bytes_read) + return ERROR_SERVER_REMOTE_CLOSED; + else if (bytes_read < 0) { + LOG_ERROR("error during read: %s", strerror(errno)); + return ERROR_SERVER_REMOTE_CLOSED; + } + + length = bytes_read; + rtt_write_channel(service->channel, buffer, &length); + + return ERROR_OK; +} + +COMMAND_HANDLER(handle_rtt_start_command) +{ + int ret; + struct rtt_service *service; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + service = malloc(sizeof(struct rtt_service)); + + if (!service) + return ERROR_FAIL; + + COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], service->channel); + + ret = add_service("rtt", CMD_ARGV[0], CONNECTION_LIMIT_UNLIMITED, + rtt_new_connection, rtt_input, rtt_connection_closed, service, NULL); + + if (ret != ERROR_OK) { + free(service); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(handle_rtt_stop_command) +{ + if (CMD_ARGC != 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + remove_service("rtt", CMD_ARGV[0]); + + return ERROR_OK; +} + +static const struct command_registration rtt_server_subcommand_handlers[] = { + { + .name = "start", + .handler = handle_rtt_start_command, + .mode = COMMAND_ANY, + .help = "Start a RTT server", + .usage = "<port> <channel>" + }, + { + .name = "stop", + .handler = handle_rtt_stop_command, + .mode = COMMAND_ANY, + .help = "Stop a RTT server", + .usage = "<port>" + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration rtt_server_command_handlers[] = { + { + .name = "server", + .mode = COMMAND_ANY, + .help = "RTT server", + .usage = "", + .chain = rtt_server_subcommand_handlers + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration rtt_command_handlers[] = { + { + .name = "rtt", + .mode = COMMAND_ANY, + .help = "RTT", + .usage = "", + .chain = rtt_server_command_handlers + }, + COMMAND_REGISTRATION_DONE +}; + +int rtt_server_register_commands(struct command_context *ctx) +{ + return register_commands(ctx, NULL, rtt_command_handlers); +} diff --git a/src/server/rtt_server.h b/src/server/rtt_server.h new file mode 100644 index 000000000..aec6f2222 --- /dev/null +++ b/src/server/rtt_server.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2016-2017 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPENOCD_SERVER_RTT_SERVER_H +#define OPENOCD_SERVER_RTT_SERVER_H + +#include <helper/command.h> + +int rtt_server_register_commands(struct command_context *ctx); + +#endif /* OPENOCD_SERVER_RTT_SERVER_H */ diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 19ba7714e..1d30747b6 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -48,7 +48,8 @@ TARGET_CORE_SRC = \ %D%/target_request.c \ %D%/testee.c \ %D%/semihosting_common.c \ - %D%/smp.c + %D%/smp.c \ + %D%/rtt.c ARMV4_5_SRC = \ %D%/armv4_5.c \ @@ -259,7 +260,8 @@ ARC_SRC = \ %D%/arc.h \ %D%/arc_cmd.h \ %D%/arc_jtag.h \ - %D%/arc_mem.h + %D%/arc_mem.h \ + %D%/rtt.h include %D%/openrisc/Makefile.am include %D%/riscv/Makefile.am diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index fae2aac5d..316089c35 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -39,6 +39,7 @@ #include "arm_opcodes.h" #include "arm_semihosting.h" #include <helper/time_support.h> +#include <rtt/rtt.h> /* NOTE: most of this should work fine for the Cortex-M1 and * Cortex-M0 cores too, although they're ARMv6-M not ARMv7-M. @@ -2489,6 +2490,9 @@ static const struct command_registration cortex_m_command_handlers[] = { .usage = "", .chain = cortex_m_exec_command_handlers, }, + { + .chain = rtt_target_command_handlers, + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 99afccc49..3d41387fd 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -39,6 +39,7 @@ #include "cortex_m.h" #include "arm_semihosting.h" #include "target_request.h" +#include <rtt/rtt.h> #define savedDCRDR dbgbase /* FIXME: using target->dbgbase to preserve DCRDR */ @@ -626,6 +627,9 @@ static const struct command_registration adapter_command_handlers[] = { { .chain = armv7m_trace_command_handlers, }, + { + .chain = rtt_target_command_handlers, + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/rtt.c b/src/target/rtt.c new file mode 100644 index 000000000..7e556e1cb --- /dev/null +++ b/src/target/rtt.c @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2016-2020 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stddef.h> +#include <stdint.h> +#include <helper/log.h> +#include <helper/binarybuffer.h> +#include <helper/command.h> +#include <rtt/rtt.h> + +#include "target.h" + +static int read_rtt_channel(struct target *target, + const struct rtt_control *ctrl, unsigned int channel_index, + enum rtt_channel_type type, struct rtt_channel *channel) +{ + int ret; + uint8_t buf[RTT_CHANNEL_SIZE]; + target_addr_t address; + + address = ctrl->address + RTT_CB_SIZE + (channel_index * RTT_CHANNEL_SIZE); + + if (type == RTT_CHANNEL_TYPE_DOWN) + address += ctrl->num_up_channels * RTT_CHANNEL_SIZE; + + ret = target_read_buffer(target, address, RTT_CHANNEL_SIZE, buf); + + if (ret != ERROR_OK) + return ret; + + channel->address = address; + channel->name_addr = buf_get_u32(buf + 0, 0, 32); + channel->buffer_addr = buf_get_u32(buf + 4, 0, 32); + channel->size = buf_get_u32(buf + 8, 0, 32); + channel->write_pos = buf_get_u32(buf + 12, 0, 32); + channel->read_pos = buf_get_u32(buf + 16, 0, 32); + channel->flags = buf_get_u32(buf + 20, 0, 32); + + return ERROR_OK; +} + +int target_rtt_start(struct target *target, const struct rtt_control *ctrl, + void *user_data) +{ + return ERROR_OK; +} + +int target_rtt_stop(struct target *target, void *user_data) +{ + return ERROR_OK; +} + +static int read_channel_name(struct target *target, target_addr_t address, + char *name, size_t length) +{ + size_t offset; + + offset = 0; + + while (offset < length) { + int ret; + size_t read_length; + + read_length = MIN(32, length - offset); + ret = target_read_buffer(target, address + offset, read_length, + (uint8_t *)name + offset); + + if (ret != ERROR_OK) + return ret; + + if (memchr(name + offset, '\0', read_length)) + return ERROR_OK; + + offset += read_length; + } + + name[length - 1] = '\0'; + + return ERROR_OK; +} + +static int write_to_channel(struct target *target, + const struct rtt_channel *channel, const uint8_t *buffer, + size_t *length) +{ + int ret; + uint32_t len; + + if (!*length) + return ERROR_OK; + + if (channel->write_pos == channel->read_pos) { + uint32_t first_length; + + len = MIN(*length, channel->size - 1); + first_length = MIN(len, channel->size - channel->write_pos); + + ret = target_write_buffer(target, + channel->buffer_addr + channel->write_pos, first_length, + buffer); + + if (ret != ERROR_OK) + return ret; + + ret = target_write_buffer(target, channel->buffer_addr, + len - first_length, buffer + first_length); + + if (ret != ERROR_OK) + return ret; + } else if (channel->write_pos < channel->read_pos) { + len = MIN(*length, channel->read_pos - channel->write_pos - 1); + + if (!len) { + *length = 0; + return ERROR_OK; + } + + ret = target_write_buffer(target, + channel->buffer_addr + channel->write_pos, len, buffer); + + if (ret != ERROR_OK) + return ret; + } else { + uint32_t first_length; + + len = MIN(*length, + channel->size - channel->write_pos + channel->read_pos - 1); + + if (!len) { + *length = 0; + return ERROR_OK; + } + + first_length = MIN(len, channel->size - channel->write_pos); + + ret = target_write_buffer(target, + channel->buffer_addr + channel->write_pos, first_length, + buffer); + + if (ret != ERROR_OK) + return ret; + + buffer = buffer + first_length; + + ret = target_write_buffer(target, channel->buffer_addr, + len - first_length, buffer); + + if (ret != ERROR_OK) + return ret; + } + + ret = target_write_u32(target, channel->address + 12, + (channel->write_pos + len) % channel->size); + + if (ret != ERROR_OK) + return ret; + + *length = len; + + return ERROR_OK; +} + +static bool channel_is_active(const struct rtt_channel *channel) +{ + if (!channel) + return false; + + if (!channel->size) + return false; + + return true; +} + +int target_rtt_write_callback(struct target *target, struct rtt_control *ctrl, + unsigned int channel_index, const uint8_t *buffer, size_t *length, + void *user_data) +{ + int ret; + struct rtt_channel channel; + + ret = read_rtt_channel(target, ctrl, channel_index, + RTT_CHANNEL_TYPE_DOWN, &channel); + + if (ret != ERROR_OK) { + LOG_ERROR("rtt: Failed to read down-channel %u description", + channel_index); + return ret; + } + + if (!channel_is_active(&channel)) { + LOG_WARNING("rtt: Down-channel %u is not active", channel_index); + return ERROR_OK; + } + + if (channel.size < RTT_CHANNEL_BUFFER_MIN_SIZE) { + LOG_WARNING("rtt: Down-channel %u is not large enough", + channel_index); + return ERROR_OK; + } + + ret = write_to_channel(target, &channel, buffer, length); + + if (ret != ERROR_OK) + return ret; + + LOG_DEBUG("rtt: Wrote %zu bytes into down-channel %u", *length, + channel_index); + + return ERROR_OK; +} + +int target_rtt_read_control_block(struct target *target, + target_addr_t address, struct rtt_control *ctrl, void *user_data) +{ + int ret; + uint8_t buf[RTT_CB_SIZE]; + + ret = target_read_buffer(target, address, RTT_CB_SIZE, buf); + + if (ret != ERROR_OK) + return ret; + + memcpy(ctrl->id, buf, RTT_CB_MAX_ID_LENGTH); + ctrl->id[RTT_CB_MAX_ID_LENGTH - 1] = '\0'; + ctrl->num_up_channels = buf_get_u32(buf + RTT_CB_MAX_ID_LENGTH + 0, + 0, 32); + ctrl->num_down_channels = buf_get_u32(buf + RTT_CB_MAX_ID_LENGTH + 4, + 0, 32); + + return ERROR_OK; +} + +int target_rtt_find_control_block(struct target *target, + target_addr_t *address, size_t size, const char *id, bool *found, + void *user_data) +{ + uint8_t buf[1024]; + + *found = false; + + size_t j = 0; + size_t cb_offset = 0; + const size_t id_length = strlen(id); + + LOG_INFO("rtt: Searching for control block '%s'", id); + + for (target_addr_t addr = 0; addr < size; addr = addr + sizeof(buf)) { + int ret; + + const size_t buf_size = MIN(sizeof(buf), size - addr); + ret = target_read_buffer(target, *address + addr, buf_size, buf); + + if (ret != ERROR_OK) + return ret; + + size_t start = 0; + size_t i = 0; + + while (i < buf_size) { + if (buf[i] != id[j]) { + start++; + cb_offset++; + i = start; + j = 0; + + continue; + } + + i++; + j++; + + if (j == id_length) { + *address = *address + cb_offset; + *found = true; + return ERROR_OK; + } + } + } + + return ERROR_OK; +} + +int target_rtt_read_channel_info(struct target *target, + const struct rtt_control *ctrl, unsigned int channel_index, + enum rtt_channel_type type, struct rtt_channel_info *info, + void *user_data) +{ + int ret; + struct rtt_channel channel; + + ret = read_rtt_channel(target, ctrl, channel_index, type, &channel); + + if (ret != ERROR_OK) { + LOG_ERROR("rtt: Failed to read channel %u description", + channel_index); + return ret; + } + + ret = read_channel_name(target, channel.name_addr, info->name, + info->name_length); + + if (ret != ERROR_OK) + return ret; + + info->size = channel.size; + info->flags = channel.flags; + + return ERROR_OK; +} + +static int read_from_channel(struct target *target, + const struct rtt_channel *channel, uint8_t *buffer, + size_t *length) +{ + int ret; + uint32_t len; + + if (!*length) + return ERROR_OK; + + if (channel->read_pos == channel->write_pos) { + len = 0; + } else if (channel->read_pos < channel->write_pos) { + len = MIN(*length, channel->write_pos - channel->read_pos); + + ret = target_read_buffer(target, + channel->buffer_addr + channel->read_pos, len, buffer); + + if (ret != ERROR_OK) + return ret; + } else { + uint32_t first_length; + + len = MIN(*length, + channel->size - channel->read_pos + channel->write_pos); + first_length = MIN(len, channel->size - channel->read_pos); + + ret = target_read_buffer(target, + channel->buffer_addr + channel->read_pos, first_length, buffer); + + if (ret != ERROR_OK) + return ret; + + ret = target_read_buffer(target, channel->buffer_addr, + len - first_length, buffer + first_length); + + if (ret != ERROR_OK) + return ret; + } + + if (len > 0) { + ret = target_write_u32(target, channel->address + 16, + (channel->read_pos + len) % channel->size); + + if (ret != ERROR_OK) + return ret; + } + + *length = len; + + return ERROR_OK; +} + +int target_rtt_read_callback(struct target *target, + const struct rtt_control *ctrl, struct rtt_sink_list **sinks, + size_t num_channels, void *user_data) +{ + num_channels = MIN(num_channels, ctrl->num_up_channels); + + for (size_t i = 0; i < num_channels; i++) { + int ret; + struct rtt_channel channel; + uint8_t buffer[1024]; + size_t length; + + if (!sinks[i]) + continue; + + ret = read_rtt_channel(target, ctrl, i, RTT_CHANNEL_TYPE_UP, + &channel); + + if (ret != ERROR_OK) { + LOG_ERROR("rtt: Failed to read up-channel %zu description", i); + return ret; + } + + if (!channel_is_active(&channel)) { + LOG_WARNING("rtt: Up-channel %zu is not active", i); + continue; + } + + if (channel.size < RTT_CHANNEL_BUFFER_MIN_SIZE) { + LOG_WARNING("rtt: Up-channel %zu is not large enough", i); + continue; + } + + length = sizeof(buffer); + ret = read_from_channel(target, &channel, buffer, &length); + + if (ret != ERROR_OK) { + LOG_ERROR("rtt: Failed to read from up-channel %zu", i); + return ret; + } + + for (struct rtt_sink_list *sink = sinks[i]; sink; sink = sink->next) + sink->read(i, buffer, length, sink->user_data); + } + + return ERROR_OK; +} diff --git a/src/target/rtt.h b/src/target/rtt.h new file mode 100644 index 000000000..01224750f --- /dev/null +++ b/src/target/rtt.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2016-2020 by Marc Schink <de...@za...> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OPENOCD_TARGET_RTT_H +#define OPENOCD_TARGET_RTT_H + +#include <stdint.h> +#include <stdbool.h> + +#include <target/target.h> +#include <rtt/rtt.h> + +int target_rtt_start(struct target *target, const struct rtt_control *ctrl, + void *user_data); +int target_rtt_stop(struct target *target, void *user_data); +int target_rtt_find_control_block(struct target *target, + target_addr_t *address, size_t size, const char *id, bool *found, + void *user_data); +int target_rtt_read_control_block(struct target *target, + target_addr_t address, struct rtt_control *ctrl, void *user_data); +int target_rtt_write_callback(struct target *target, + struct rtt_control *ctrl, unsigned int channel_index, + const uint8_t *buffer, size_t *length, void *user_data); +int target_rtt_read_callback(struct target *target, + const struct rtt_control *ctrl, struct rtt_sink_list **sinks, + size_t length, void *user_data); +int target_rtt_read_channel_info(struct target *target, + const struct rtt_control *ctrl, unsigned int channel_index, + enum rtt_channel_type type, struct rtt_channel_info *info, + void *user_data); + +#endif /* OPENOCD_TARGET_RTT_H */ ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 88 ++++++++++ src/Makefile.am | 4 +- src/openocd.c | 7 + src/rtt/Makefile.am | 2 + src/rtt/rtt.c | 332 +++++++++++++++++++++++++++++++++++++ src/rtt/rtt.h | 287 ++++++++++++++++++++++++++++++++ src/rtt/tcl.c | 311 +++++++++++++++++++++++++++++++++++ src/server/Makefile.am | 4 +- src/server/rtt_server.c | 192 ++++++++++++++++++++++ src/server/rtt_server.h | 25 +++ src/target/Makefile.am | 6 +- src/target/cortex_m.c | 4 + src/target/hla_target.c | 4 + src/target/rtt.c | 424 ++++++++++++++++++++++++++++++++++++++++++++++++ src/target/rtt.h | 46 ++++++ 15 files changed, 1732 insertions(+), 4 deletions(-) create mode 100644 src/rtt/Makefile.am create mode 100644 src/rtt/rtt.c create mode 100644 src/rtt/rtt.h create mode 100644 src/rtt/tcl.c create mode 100644 src/server/rtt_server.c create mode 100644 src/server/rtt_server.h create mode 100644 src/target/rtt.c create mode 100644 src/target/rtt.h hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-12-02 23:17:07
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via d459a2d27df52643dc8932827a63467a14f7c162 (commit) via 646c3c99020f8fdf7ee0adf821582238aac4a80c (commit) from a8edbd0200560bfd412c5c563908d860ed2c96a6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d459a2d27df52643dc8932827a63467a14f7c162 Author: Tomas Vanek <va...@fb...> Date: Fri Mar 1 21:44:27 2019 +0100 adi_v5_swd: wait for readable DPIDR, ABORT if stalled Reading of DPIDR is the very first operation after JTAG to SWD sequence. Without this change if DPIDR read fails then swd connect fails. Keep trying JTAG to SWD sequence and DPIDR read until success or timeout 0.5 sec. It makes setting of adapter srst delay on SWD transport mostly unnecessary. Also test for ERROR_WAIT (which should not occur according to IHI 0031E B4.3.2 but a quirk is known) and if bus is kept stalled then issue abort to make the next connect possible. Change-Id: Id8fe6618605bbeb4fed5061e987ed55de90a35f2 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5730 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Andreas Fritiofson <and...@gm...> diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index ee30ff7ba..b25181e21 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -118,26 +118,69 @@ static int swd_connect(struct adiv5_dap *dap) } } - /* Note, debugport_init() does setup too */ - swd->switch_seq(JTAG_TO_SWD); - /* Clear link state, including the SELECT cache. */ - dap->do_reconnect = false; - dap_invalidate_cache(dap); + int64_t timeout = timeval_ms() + 500; - swd_queue_dp_read(dap, DP_DPIDR, &dpidr); + do { + /* Note, debugport_init() does setup too */ + swd->switch_seq(JTAG_TO_SWD); - /* force clear all sticky faults */ - swd_clear_sticky_errors(dap); + /* Clear link state, including the SELECT cache. */ + dap->do_reconnect = false; + dap_invalidate_cache(dap); + + status = swd_queue_dp_read(dap, DP_DPIDR, &dpidr); + if (status == ERROR_OK) { + status = swd_run_inner(dap); + if (status == ERROR_OK) + break; + } + + alive_sleep(1); + + } while (timeval_ms() < timeout); + + if (status != ERROR_OK) { + LOG_ERROR("Error connecting DP: cannot read IDR"); + return status; + } + + LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr); + + do { + dap->do_reconnect = false; - status = swd_run_inner(dap); + /* force clear all sticky faults */ + swd_clear_sticky_errors(dap); + + status = swd_run_inner(dap); + if (status != ERROR_WAIT) + break; + + alive_sleep(10); + + } while (timeval_ms() < timeout); + + /* IHI 0031E B4.3.2: + * "A WAIT response must not be issued to the ... + * ... writes to the ABORT register" + * swd_clear_sticky_errors() writes to the ABORT register only. + * + * Unfortunately at least Microchip SAMD51/E53/E54 returns WAIT + * in a corner case. Just try if ABORT resolves the problem. + */ + if (status == ERROR_WAIT) { + LOG_WARNING("Connecting DP: stalled AP operation, issuing ABORT"); - if (status == ERROR_OK) { - LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr); dap->do_reconnect = false; + + swd->write_reg(swd_cmd(false, false, DP_ABORT), + DAPABORT | STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR, 0); + status = swd_run_inner(dap); + } + + if (status == ERROR_OK) status = dap_dp_init(dap); - } else - dap->do_reconnect = true; return status; } commit 646c3c99020f8fdf7ee0adf821582238aac4a80c Author: Tomas Vanek <va...@fb...> Date: Mon Jun 29 13:34:07 2020 +0200 arm_adi_v5: prevent possibly endless recursion in dap_dp_init() If dap_dp_read_atomic() in 30 trials loop fails, dap->do_reconnect is set. Following dap_dp_read_atomic() calls dap_queue_dp_read() which in case of SWD transport calls swd_queue_dp_read(). It starts with swd_check_reconnect() and it calls swd_connect() because dap->do_reconnect is set. swd_connect() does some initialization, reads DPIDR and calls dap_dp_init() again! Moreover if dap_dp_init() is called from cortex_m_reset_(de)assert() one level of recursion is necessary to reconnect the target. Introduce dap_dp_init_or_reconnect() for use in cortex_m reset and similar. Remove loop of 30 atomic reads of DP_STAT to prevent unwanted recursion. Change-Id: I54052fdefe50bf5f7c7b59fe751fe2063d5710c9 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5729 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Andreas Fritiofson <and...@gm...> diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 31c14597b..59bb186c6 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -652,35 +652,22 @@ int dap_dp_init(struct adiv5_dap *dap) LOG_DEBUG("%s", adiv5_dap_name(dap)); + dap->do_reconnect = false; dap_invalidate_cache(dap); /* * Early initialize dap->dp_ctrl_stat. - * In jtag mode only, if the following atomic reads fail and set the - * sticky error, it will trigger the clearing of the sticky. Without this - * initialization system and debug power would be disabled while clearing - * the sticky error bit. + * In jtag mode only, if the following queue run (in dap_dp_poll_register) + * fails and sets the sticky error, it will trigger the clearing + * of the sticky. Without this initialization system and debug power + * would be disabled while clearing the sticky error bit. */ dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; - for (size_t i = 0; i < 30; i++) { - /* DP initialization */ - - retval = dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL); - if (retval == ERROR_OK) - break; - } - /* * This write operation clears the sticky error bit in jtag mode only and * is ignored in swd mode. It also powers-up system and debug domains in * both jtag and swd modes, if not done before. - * Actually we do not need to clear the sticky error here because it has - * been already cleared (if it was set) in the previous atomic read. This - * write could be removed, but this initial part of dap_dp_init() is the - * result of years of fine tuning and there are strong concerns about any - * unnecessary code change. It doesn't harm, so let's keep it here and - * preserve the historical sequence of read/write operations! */ retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat | SSTICKYERR); if (retval != ERROR_OK) @@ -731,6 +718,35 @@ int dap_dp_init(struct adiv5_dap *dap) return retval; } +/** + * Initialize a DAP or do reconnect if DAP is not accessible. + * + * @param dap The DAP being initialized. + */ +int dap_dp_init_or_reconnect(struct adiv5_dap *dap) +{ + LOG_DEBUG("%s", adiv5_dap_name(dap)); + + /* + * Early initialize dap->dp_ctrl_stat. + * In jtag mode only, if the following atomic reads fail and set the + * sticky error, it will trigger the clearing of the sticky. Without this + * initialization system and debug power would be disabled while clearing + * the sticky error bit. + */ + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + + dap->do_reconnect = false; + + dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL); + if (dap->do_reconnect) { + /* dap connect calls dap_dp_init() after transport dependent initialization */ + return dap->ops->connect(dap); + } else { + return dap_dp_init(dap); + } +} + /** * Initialize a DAP. This sets up the power domains, prepares the DP * for further use, and arranges to use AP #0 for all AP operations diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index f319a062d..8edfaa816 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -550,6 +550,7 @@ int mem_ap_write_buf_noincr(struct adiv5_ap *ap, /* Initialisation of the debug system, power domains and registers */ int dap_dp_init(struct adiv5_dap *dap); +int dap_dp_init_or_reconnect(struct adiv5_dap *dap); int mem_ap_init(struct adiv5_ap *ap); /* Invalidate cached DP select and cached TAR and CSW of all APs */ diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 94cf82489..fae2aac5d 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1202,11 +1202,13 @@ static int cortex_m_assert_reset(struct target *target) if (retval3 != ERROR_OK) LOG_DEBUG("Ignoring AP write error right after reset"); - retval3 = dap_dp_init(armv7m->debug_ap->dap); - if (retval3 != ERROR_OK) + retval3 = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); + if (retval3 != ERROR_OK) { LOG_ERROR("DP initialisation failed"); - - else { + /* The error return value must not be propagated in this case. + * SYSRESETREQ or VECTRESET have been possibly triggered + * so reset processing should continue */ + } else { /* I do not know why this is necessary, but it * fixes strange effects (step/resume cause NMI * after reset) on LM3S6918 -- Michael Schwingen @@ -1249,7 +1251,8 @@ static int cortex_m_deassert_reset(struct target *target) if ((jtag_reset_config & RESET_HAS_SRST) && !(jtag_reset_config & RESET_SRST_NO_GATING) && target_was_examined(target)) { - int retval = dap_dp_init(armv7m->debug_ap->dap); + + int retval = dap_dp_init_or_reconnect(armv7m->debug_ap->dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); return retval; ----------------------------------------------------------------------- Summary of changes: src/target/adi_v5_swd.c | 69 +++++++++++++++++++++++++++++++++++++++---------- src/target/arm_adi_v5.c | 52 ++++++++++++++++++++++++------------- src/target/arm_adi_v5.h | 1 + src/target/cortex_m.c | 13 ++++++---- 4 files changed, 99 insertions(+), 36 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 22:12:45
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via a8edbd0200560bfd412c5c563908d860ed2c96a6 (commit) from a03ac1ba3087ffedb3064e926624eda6cda8f808 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a8edbd0200560bfd412c5c563908d860ed2c96a6 Author: Tarek BOCHKATI <tar...@st...> Date: Sun Nov 8 21:48:14 2020 +0100 tcl/target: remove deprecated ${target}_${adapter}.cfg files Change-Id: Ic4837ad3bd06eb353020e44638306f341a923c05 Signed-off-by: Tarek BOCHKATI <tar...@st...> Reviewed-on: http://openocd.zylin.com/5929 Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/tcl/target/efm32_stlink.cfg b/tcl/target/efm32_stlink.cfg deleted file mode 100644 index 230155ea0..000000000 --- a/tcl/target/efm32_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/efm32_stlink.cfg is deprecated, please switch to target/efm32.cfg" -source [find target/efm32.cfg] diff --git a/tcl/target/kl25z_hla.cfg b/tcl/target/kl25z_hla.cfg deleted file mode 100644 index e4deac615..000000000 --- a/tcl/target/kl25z_hla.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/kl25z_hla.cfg is deprecated, please switch to target/kl25.cfg" -source [find target/kl25.cfg] diff --git a/tcl/target/nrf51_stlink.tcl b/tcl/target/nrf51_stlink.tcl deleted file mode 100644 index 7e23c5a74..000000000 --- a/tcl/target/nrf51_stlink.tcl +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/nrf51_stlink.cfg is deprecated, please switch to target/nrf51.cfg" -source [find target/nrf51.cfg] diff --git a/tcl/target/stellaris_icdi.cfg b/tcl/target/stellaris_icdi.cfg deleted file mode 100644 index f856a7a8d..000000000 --- a/tcl/target/stellaris_icdi.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stellaris_icdi.cfg is deprecated, please switch to target/stellaris.cfg" -source [find target/stellaris.cfg] diff --git a/tcl/target/stm32_stlink.cfg b/tcl/target/stm32_stlink.cfg deleted file mode 100644 index 295292e3e..000000000 --- a/tcl/target/stm32_stlink.cfg +++ /dev/null @@ -1 +0,0 @@ -echo "WARNING: stm32_stlink.cfg is deprecated (and does nothing, you can safely remove it.)" diff --git a/tcl/target/stm32f0x_stlink.cfg b/tcl/target/stm32f0x_stlink.cfg deleted file mode 100644 index cecfb7a78..000000000 --- a/tcl/target/stm32f0x_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32f0x_stlink.cfg is deprecated, please switch to target/stm32f0x.cfg" -source [find target/stm32f0x.cfg] diff --git a/tcl/target/stm32f1x_stlink.cfg b/tcl/target/stm32f1x_stlink.cfg deleted file mode 100644 index 0a3e6430e..000000000 --- a/tcl/target/stm32f1x_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32f1x_stlink.cfg is deprecated, please switch to target/stm32f1x.cfg" -source [find target/stm32f1x.cfg] diff --git a/tcl/target/stm32f2x_stlink.cfg b/tcl/target/stm32f2x_stlink.cfg deleted file mode 100644 index 451b2b5e2..000000000 --- a/tcl/target/stm32f2x_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32f2x_stlink.cfg is deprecated, please switch to target/stm32f2x.cfg" -source [find target/stm32f2x.cfg] diff --git a/tcl/target/stm32f3x_stlink.cfg b/tcl/target/stm32f3x_stlink.cfg deleted file mode 100644 index 87693586d..000000000 --- a/tcl/target/stm32f3x_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32f3x_stlink.cfg is deprecated, please switch to target/stm32f3x.cfg" -source [find target/stm32f3x.cfg] diff --git a/tcl/target/stm32f4x_stlink.cfg b/tcl/target/stm32f4x_stlink.cfg deleted file mode 100644 index af3e8a098..000000000 --- a/tcl/target/stm32f4x_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32f4x_stlink.cfg is deprecated, please switch to target/stm32f4x.cfg" -source [find target/stm32f4x.cfg] diff --git a/tcl/target/stm32lx_stlink.cfg b/tcl/target/stm32lx_stlink.cfg deleted file mode 100644 index 5f694b546..000000000 --- a/tcl/target/stm32lx_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32lx_stlink.cfg is deprecated, please switch to target/stm32l1.cfg" -source [find target/stm32l1.cfg] diff --git a/tcl/target/stm32w108_stlink.cfg b/tcl/target/stm32w108_stlink.cfg deleted file mode 100644 index 120feea94..000000000 --- a/tcl/target/stm32w108_stlink.cfg +++ /dev/null @@ -1,2 +0,0 @@ -echo "WARNING: target/stm32w108xx_stlink.cfg is deprecated, please switch to target/stm32w108xx.cfg" -source [find target/stm32w108xx.cfg] ----------------------------------------------------------------------- Summary of changes: tcl/target/efm32_stlink.cfg | 2 -- tcl/target/kl25z_hla.cfg | 2 -- tcl/target/nrf51_stlink.tcl | 2 -- tcl/target/stellaris_icdi.cfg | 2 -- tcl/target/stm32_stlink.cfg | 1 - tcl/target/stm32f0x_stlink.cfg | 2 -- tcl/target/stm32f1x_stlink.cfg | 2 -- tcl/target/stm32f2x_stlink.cfg | 2 -- tcl/target/stm32f3x_stlink.cfg | 2 -- tcl/target/stm32f4x_stlink.cfg | 2 -- tcl/target/stm32lx_stlink.cfg | 2 -- tcl/target/stm32w108_stlink.cfg | 2 -- 12 files changed, 23 deletions(-) delete mode 100644 tcl/target/efm32_stlink.cfg delete mode 100644 tcl/target/kl25z_hla.cfg delete mode 100644 tcl/target/nrf51_stlink.tcl delete mode 100644 tcl/target/stellaris_icdi.cfg delete mode 100644 tcl/target/stm32_stlink.cfg delete mode 100644 tcl/target/stm32f0x_stlink.cfg delete mode 100644 tcl/target/stm32f1x_stlink.cfg delete mode 100644 tcl/target/stm32f2x_stlink.cfg delete mode 100644 tcl/target/stm32f3x_stlink.cfg delete mode 100644 tcl/target/stm32f4x_stlink.cfg delete mode 100644 tcl/target/stm32lx_stlink.cfg delete mode 100644 tcl/target/stm32w108_stlink.cfg hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 22:11:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via a03ac1ba3087ffedb3064e926624eda6cda8f808 (commit) from 61326940361b2242feb8adfefb9ca12727154693 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a03ac1ba3087ffedb3064e926624eda6cda8f808 Author: Tomas Vanek <va...@fb...> Date: Sun Nov 8 13:46:39 2020 +0100 helper/command: disable logging of registered commands [RFC] Every debug log of OpenOCD contains approximately 130 lines like: Debug: 264 147 command.c:354 register_command_handler(): registering 'flash'... Because only root name of the command is logged, most of lines is not too informative. E.g. registering 'flash' is repeated 14 times. Karl Passon submitted the patch [1] changing the logged cmd name from root to lowest level. It makes the log better. Unfortunately we also have 'reset_config' and 'cortex_m reset_config' and similar which looks equal in the log after [1]. Moreover [1] has not been reviewed for 5 years. So my guess is that nobody uses that crap in debug log. Save more than 10 kbytes in any debug log and make log analyse easier by blocking log command in #if 0 block. If some developer eventually needs to debug cmd registering he can easily enable logging again. [1] http://openocd.zylin.com/2765 Change-Id: Ib7e528aadd692fd0da2e3c005b4c5a484551b728 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5928 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Christopher Head <ch...@za...> diff --git a/src/helper/command.c b/src/helper/command.c index 773195e2f..0a711e514 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -349,7 +349,9 @@ static int register_command_handler(struct command_context *cmd_ctx, { Jim_Interp *interp = cmd_ctx->interp; +#if 0 LOG_DEBUG("registering '%s'...", c->name); +#endif Jim_CmdProc *func = c->handler ? &script_command : &command_unknown; int retval = Jim_CreateCommand(interp, c->name, func, c, NULL); ----------------------------------------------------------------------- Summary of changes: src/helper/command.c | 2 ++ 1 file changed, 2 insertions(+) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 22:11:17
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 61326940361b2242feb8adfefb9ca12727154693 (commit) from 726b0c592884566a7580780418ba763ffc51c745 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 61326940361b2242feb8adfefb9ca12727154693 Author: Tomas Vanek <va...@fb...> Date: Sun Nov 8 10:09:33 2020 +0100 flash/nor/stm32f1x: fix error message Backported from gd32vf103.c Change-Id: I9c5bb7b36e6efcee0473c97047058ef26cc46eb7 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5927 Reviewed-by: Antonio Borneo <bor...@gm...> Tested-by: jenkins diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 78efc8b47..9cd282d65 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -215,7 +215,7 @@ static int stm32x_check_operation_supported(struct flash_bank *bank) /* if we have a dual flash bank device then * we need to perform option byte stuff on bank0 only */ if (stm32x_info->register_base != FLASH_REG_BASE_B0) { - LOG_ERROR("Option Byte Operation's must use bank0"); + LOG_ERROR("Option byte operations must use bank 0"); return ERROR_FLASH_OPERATION_FAILED; } ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32f1x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:57:18
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 726b0c592884566a7580780418ba763ffc51c745 (commit) from 3d736e0488bc498358e3d49d7ce728b17955c8fe (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 726b0c592884566a7580780418ba763ffc51c745 Author: Tarek BOCHKATI <tar...@gm...> Date: Sun Mar 22 19:36:12 2020 +0100 stm32l4x: cosmetic simplification of get_stm32l4_info Change-Id: I2542f946f64388d908b1502f869643080fce9f9e Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5536 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Andreas Bolsch <hyp...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 2bf291368..55a8d8ff3 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -1218,19 +1218,17 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) for (unsigned int i = 0; i < part_info->num_revs; i++) { if (rev_id == part_info->revs[i].rev) { rev_str = part_info->revs[i].str; - - if (rev_str != NULL) { - snprintf(buf, buf_size, "%s - Rev: %s%s", - part_info->device_str, rev_str, stm32l4_info->probed ? - (stm32l4_info->dual_bank_mode ? " dual-bank" : " single-bank") : ""); - return ERROR_OK; - } + break; } } - snprintf(buf, buf_size, "%s - Rev: unknown (0x%04x)%s", - part_info->device_str, rev_id, stm32l4_info->probed ? - (stm32l4_info->dual_bank_mode ? " dual-bank" : " single-bank") : ""); + int buf_len = snprintf(buf, buf_size, "%s - Rev %s : 0x%04x", + part_info->device_str, rev_str ? rev_str : "'unknown'", rev_id); + + if (stm32l4_info->probed) + snprintf(buf + buf_len, buf_size - buf_len, " - %s-bank", + stm32l4_info->dual_bank_mode ? "Flash dual" : "Flash single"); + return ERROR_OK; } else { snprintf(buf, buf_size, "Cannot identify target as an %s device", device_families); ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:56:43
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 3d736e0488bc498358e3d49d7ce728b17955c8fe (commit) from dc43ecce5a7ee5722ea851707ad3acd08a42b5aa (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3d736e0488bc498358e3d49d7ce728b17955c8fe Author: Tarek BOCHKATI <tar...@gm...> Date: Wed Mar 25 16:33:30 2020 +0100 flash/stm32l4x: STM32L55/L56xx basic support (non-secure mode) STM32L5 have 512 Kbytes of Flash memory with dual bank architecture. STM32L5 flash is quite similar to L4 flash, mainly register names and offsets and some bits are changed. NON-SECURE flash is located at 0x8000000 like L4 devices, so no big change is needed (secure flash will be subject of another change). Note: flash driver name is set stm32l5x, in order to extend the commands with specific L5 commands (to manage TZEN for example ...) Note: this works only when TZEN=0 Change-Id: Ie758abb4aa19a3f29eeb0702d7dcb43992e4c639 Signed-off-by: Michael Jung <mi...@gm...> Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5510 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 292bbd77c..65b5d65b2 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7134,10 +7134,9 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @deffn {Flash Driver} stm32l4x -All members of the STM32L4, STM32L4+, STM32WB, STM32WL and STM32G4 +All members of the STM32 G0, G4, L4, L4+, L5, WB and WL microcontroller families from STMicroelectronics include internal flash -and use ARM Cortex-M4 cores. -Additionally this driver supports STM32G0 family with ARM Cortex-M0+ core. +and use ARM Cortex-M0+, M4 and M33 cores. The driver automatically recognizes a number of these chips using the chip identification register, and autoconfigures itself. diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index ca8a3b81d..2bf291368 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -106,6 +106,12 @@ * Cat. 4 devices have single bank only, page size is 2kByte. */ +/* STM32L5xxx series for reference. + * + * RM0428 (STM32L552xx/STM32L562xx) + * http://www.st.com/resource/en/reference_manual/dm00346336.pdf + */ + /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ #define FLASH_ERASE_TIMEOUT 250 @@ -137,6 +143,19 @@ static const uint32_t stm32l4_flash_regs[STM32_FLASH_REG_INDEX_NUM] = { [STM32_FLASH_WRP2BR_INDEX] = 0x050, }; +static const uint32_t stm32l5_ns_flash_regs[STM32_FLASH_REG_INDEX_NUM] = { + [STM32_FLASH_ACR_INDEX] = 0x000, + [STM32_FLASH_KEYR_INDEX] = 0x008, + [STM32_FLASH_OPTKEYR_INDEX] = 0x010, + [STM32_FLASH_SR_INDEX] = 0x020, + [STM32_FLASH_CR_INDEX] = 0x028, + [STM32_FLASH_OPTR_INDEX] = 0x040, + [STM32_FLASH_WRP1AR_INDEX] = 0x058, + [STM32_FLASH_WRP1BR_INDEX] = 0x05C, + [STM32_FLASH_WRP2AR_INDEX] = 0x068, + [STM32_FLASH_WRP2BR_INDEX] = 0x06C, +}; + struct stm32l4_rev { const uint16_t rev; const char *str; @@ -167,7 +186,7 @@ struct stm32l4_flash_bank { }; /* human readable list of families this drivers supports (sorted alphabetically) */ -static const char *device_families = "STM32G0/G4/L4/L4+/WB/WL"; +static const char *device_families = "STM32G0/G4/L4/L4+/L5/WB/WL"; static const struct stm32l4_rev stm32_415_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } @@ -213,6 +232,10 @@ static const struct stm32l4_rev stm32_471_revs[] = { { 0x1001, "Z" }, }; +static const struct stm32l4_rev stm32_472_revs[] = { + { 0x1000, "A" }, { 0x2000, "B" }, +}; + static const struct stm32l4_rev stm32_479_revs[] = { { 0x1000, "A" }, }; @@ -351,6 +374,17 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, + { + .id = 0x472, + .revs = stm32_472_revs, + .num_revs = ARRAY_SIZE(stm32_472_revs), + .device_str = "STM32L55/L56xx", + .max_flash_size_kb = 512, + .has_dual_bank = true, + .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l5_ns_flash_regs, + .fsize_addr = 0x0BFA05E0, + }, { .id = 0x479, .revs = stm32_479_revs, @@ -477,7 +511,6 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) alive_sleep(1); } - if (status & FLASH_WRPERR) { LOG_ERROR("stm32x device protected"); retval = ERROR_FAIL; @@ -917,17 +950,17 @@ static int stm32l4_read_idcode(struct flash_bank *bank, uint32_t *id) { int retval; - /* try stm32l4/l4+/wb/g4 id register first, then stm32g0 id register */ - retval = target_read_u32(bank->target, DBGMCU_IDCODE_L4_G4, id); - if ((retval != ERROR_OK) || ((*id & 0xfff) == 0) || ((*id & 0xfff) == 0xfff)) { - retval = target_read_u32(bank->target, DBGMCU_IDCODE_G0, id); - if ((retval != ERROR_OK) || ((*id & 0xfff) == 0) || ((*id & 0xfff) == 0xfff)) { - LOG_ERROR("can't get device id"); - return (retval == ERROR_OK) ? ERROR_FAIL : retval; - } + /* try reading possible IDCODE registers, in the following order */ + uint32_t DBGMCU_IDCODE[] = {DBGMCU_IDCODE_L4_G4, DBGMCU_IDCODE_G0, DBGMCU_IDCODE_L5}; + + for (unsigned int i = 0; i < ARRAY_SIZE(DBGMCU_IDCODE); i++) { + retval = target_read_u32(bank->target, DBGMCU_IDCODE[i], id); + if ((retval == ERROR_OK) && ((*id & 0xfff) != 0) && ((*id & 0xfff) != 0xfff)) + return ERROR_OK; } - return retval; + LOG_ERROR("can't get the device id"); + return (retval == ERROR_OK) ? ERROR_FAIL : retval; } static int stm32l4_probe(struct flash_bank *bank) @@ -1004,6 +1037,7 @@ static int stm32l4_probe(struct flash_bank *bank) int page_size_kb = 0; stm32l4_info->dual_bank_mode = false; + bool use_dbank_bit = false; switch (device_id) { case 0x415: /* STM32L47/L48xx */ @@ -1070,7 +1104,7 @@ static int stm32l4_probe(struct flash_bank *bank) page_size_kb = 8; num_pages = flash_size_kb / page_size_kb; stm32l4_info->bank1_sectors = num_pages; - const bool use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb; + use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb; if ((use_dbank_bit && (options & BIT(22))) || (!use_dbank_bit && (options & BIT(21)))) { stm32l4_info->dual_bank_mode = true; @@ -1079,6 +1113,23 @@ static int stm32l4_probe(struct flash_bank *bank) stm32l4_info->bank1_sectors = num_pages / 2; } break; + case 0x472: /* STM32L55/L56xx */ + /* STM32L55/L56xx can be single/dual bank: + * if size = 512K check DBANK bit(22) + * if size = 256K check DB256K bit(21) + */ + page_size_kb = 4; + num_pages = flash_size_kb / page_size_kb; + stm32l4_info->bank1_sectors = num_pages; + use_dbank_bit = flash_size_kb == part_info->max_flash_size_kb; + if ((use_dbank_bit && (options & BIT(22))) || + (!use_dbank_bit && (options & BIT(21)))) { + stm32l4_info->dual_bank_mode = true; + page_size_kb = 2; + num_pages = flash_size_kb / page_size_kb; + stm32l4_info->bank1_sectors = num_pages / 2; + } + break; case 0x495: /* STM32WB5x */ case 0x496: /* STM32WB3x */ /* single bank flash */ diff --git a/src/flash/startup.tcl b/src/flash/startup.tcl index aafb939cd..280a059a3 100644 --- a/src/flash/startup.tcl +++ b/src/flash/startup.tcl @@ -116,6 +116,7 @@ proc stm32l1x args { eval stm32lx $args } # stm32[g0|g4|wb|wl] uses the same flash driver as the stm32l4x proc stm32g0x args { eval stm32l4x $args } proc stm32g4x args { eval stm32l4x $args } +proc stm32l5x args { eval stm32l4x $args } proc stm32wbx args { eval stm32l4x $args } proc stm32wlx args { eval stm32l4x $args } diff --git a/tcl/board/st_nucleo_l5.cfg b/tcl/board/st_nucleo_l5.cfg new file mode 100644 index 000000000..6450f08b8 --- /dev/null +++ b/tcl/board/st_nucleo_l5.cfg @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# This is for STM32L5 Nucleo Dev Boards. +# http://www.st.com/en/evaluation-tools/stm32-mcu-nucleo.html + +source [find interface/stlink-dap.cfg] + +transport select dapdirect_swd + +source [find target/stm32l5x.cfg] + +# use hardware reset +reset_config srst_only srst_nogate diff --git a/tcl/target/stm32l5x.cfg b/tcl/target/stm32l5x.cfg new file mode 100644 index 000000000..bf5636094 --- /dev/null +++ b/tcl/target/stm32l5x.cfg @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# script for stm32l5x family + +# +# stm32l5 devices support both JTAG and SWD transports. +# +source [find target/swj-dp.tcl] +source [find mem_helper.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME stm32l5x +} + +set _ENDIAN little + +# Work-area is a space in RAM used for flash programming +# By default use 64kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x10000 +} + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + if { [using_jtag] } { + # See STM Document RM0438 + # RM0438 Rev5, Section 52.2.8 JTAG debug port - Table 425. JTAG-DP data registers + # Corresponds to Cortex®-M33 JTAG debug port ID code + set _CPUTAPID 0x0ba04477 + } { + # SWD IDCODE (single drop, arm) + set _CPUTAPID 0x0be12477 + } +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +if {[using_jtag]} { + jtag newtap $_CHIPNAME bs -irlen 5 +} + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap + +# use non-secure RAM by default +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +# declare non-secure flash +flash bank $_CHIPNAME.flash_ns stm32l4x 0 0 0 0 $_TARGETNAME + +# Common knowledges tells JTAG speed should be <= F_CPU/6. +# F_CPU after reset is MSI 4MHz, so use F_JTAG = 500 kHz to stay on +# the safe side. +# +# Note that there is a pretty wide band where things are +# more or less stable, see http://openocd.zylin.com/#/c/3366/ +adapter speed 500 + +adapter srst delay 100 +if {[using_jtag]} { + jtag_ntrst_delay 100 +} + +reset_config srst_nogate + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +proc clock_config_110_mhz {} { + # MCU clock is MSI (4MHz) after reset, set MCU freq at 110 MHz with PLL + # RCC_APB1ENR1 = PWREN + mww 0x40021058 0x10000000 + # delay for register clock enable (read back reg) + mrw 0x40021058 + # PWR_CR1 : VOS Range 0 + mww 0x40007000 0 + # while (PWR_SR2 & VOSF) + while {([mrw 0x40007014] & 0x0400)} {} + # FLASH_ACR : 5 WS for 110 MHz HCLK + mww 0x40022000 0x00000005 + # RCC_PLLCFGR = PLLP=PLLQ=0, PLLR=00=2, PLLREN=1, PLLN=55, PLLM=0000=1, PLLSRC=MSI 4MHz + # fVCO = 4 x 55 /1 = 220 + # SYSCLOCK = fVCO/PLLR = 220/2 = 110 MHz + mww 0x4002100C 0x01003711 + # RCC_CR |= PLLON + mmw 0x40021000 0x01000000 0 + # while !(RCC_CR & PLLRDY) + while {!([mrw 0x40021000] & 0x02000000)} {} + # RCC_CFGR |= SW_PLL + mmw 0x40021008 0x00000003 0 + # while ((RCC_CFGR & SWS) != PLL) + while {([mrw 0x40021008] & 0x0C) != 0x0C} {} +} + +$_TARGETNAME configure -event reset-init { + clock_config_110_mhz + # Boost JTAG frequency + adapter speed 4000 +} + +$_TARGETNAME configure -event reset-start { + # Reset clock is MSI (4 MHz) + adapter speed 480 +} + +$_TARGETNAME configure -event examine-end { + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP + mmw 0xE0044004 0x00000006 0 + + # Stop watchdog counters during halt + # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0xE0044008 0x00001800 0 +} + +$_TARGETNAME configure -event trace-config { + # Set TRACE_IOEN; TRACE_MODE is set to async; when using sync + # change this value accordingly to configure trace pins + # assignment + mmw 0xE0044004 0x00000020 0 +} ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 5 +- src/flash/nor/stm32l4x.c | 75 +++++++++++++++++++++----- src/flash/startup.tcl | 1 + tcl/board/st_nucleo_l5.cfg | 13 +++++ tcl/target/stm32l5x.cfg | 130 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 209 insertions(+), 15 deletions(-) create mode 100644 tcl/board/st_nucleo_l5.cfg create mode 100644 tcl/target/stm32l5x.cfg hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:43:22
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via dc43ecce5a7ee5722ea851707ad3acd08a42b5aa (commit) from 44cf202ef585ea5e2dda78e65cc5d04e08129eff (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit dc43ecce5a7ee5722ea851707ad3acd08a42b5aa Author: Tarek BOCHKATI <tar...@gm...> Date: Tue Nov 3 01:58:59 2020 +0100 flash/stm32l4x: introduce table with register offsets This change is a preparation for STM32L5 support on top of L4 driver STM32L5 flash is quite similar to L4 flash, mainly register names and offsets and some bits are changed. flash_regs table is introduced within stm32l4_flash_bank struct in order to get correct register offsets, by using the driver internal function 'stm32l4_get_flash_reg_by_index'. To use efficiently register indexes, stm32l4 _[get|read|write]_flash_reg functions are surcharged to accept register indexes. IMPORTANT: stm32l4_write_option is not surcharged, and they always accept the option register offset. tested on NUCLEO-G474RE and STM32L4R9I-DISCO Change-Id: I739d3e97d63b831af6aa569c5629db0000209551 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5509 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 9bdc2dbca..ca8a3b81d 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -81,8 +81,7 @@ * http://www.st.com/resource/en/reference_manual/dm00530369.pdf */ -/* - * STM32G0xxx series for reference. +/* STM32G0xxx series for reference. * * RM0444 (STM32G0x1) * http://www.st.com/resource/en/reference_manual/dm00371828.pdf @@ -91,8 +90,7 @@ * http://www.st.com/resource/en/reference_manual/dm00463896.pdf */ -/* - * STM32G4xxx series for reference. +/* STM32G4xxx series for reference. * * RM0440 (STM32G43x/44x/47x/48x/49x/4Ax) * http://www.st.com/resource/en/reference_manual/dm00355726.pdf @@ -112,6 +110,33 @@ #define FLASH_ERASE_TIMEOUT 250 +enum stm32l4_flash_reg_index { + STM32_FLASH_ACR_INDEX, + STM32_FLASH_KEYR_INDEX, + STM32_FLASH_OPTKEYR_INDEX, + STM32_FLASH_SR_INDEX, + STM32_FLASH_CR_INDEX, + STM32_FLASH_OPTR_INDEX, + STM32_FLASH_WRP1AR_INDEX, + STM32_FLASH_WRP1BR_INDEX, + STM32_FLASH_WRP2AR_INDEX, + STM32_FLASH_WRP2BR_INDEX, + STM32_FLASH_REG_INDEX_NUM, +}; + +static const uint32_t stm32l4_flash_regs[STM32_FLASH_REG_INDEX_NUM] = { + [STM32_FLASH_ACR_INDEX] = 0x000, + [STM32_FLASH_KEYR_INDEX] = 0x008, + [STM32_FLASH_OPTKEYR_INDEX] = 0x00C, + [STM32_FLASH_SR_INDEX] = 0x010, + [STM32_FLASH_CR_INDEX] = 0x014, + [STM32_FLASH_OPTR_INDEX] = 0x020, + [STM32_FLASH_WRP1AR_INDEX] = 0x02C, + [STM32_FLASH_WRP1BR_INDEX] = 0x030, + [STM32_FLASH_WRP2AR_INDEX] = 0x04C, + [STM32_FLASH_WRP2BR_INDEX] = 0x050, +}; + struct stm32l4_rev { const uint16_t rev; const char *str; @@ -125,6 +150,7 @@ struct stm32l4_part_info { const uint16_t max_flash_size_kb; const bool has_dual_bank; const uint32_t flash_regs_base; + const uint32_t *default_flash_regs; const uint32_t fsize_addr; }; @@ -137,10 +163,11 @@ struct stm32l4_flash_bank { uint32_t user_bank_size; uint32_t wrpxxr_mask; const struct stm32l4_part_info *part_info; + const uint32_t *flash_regs; }; -/* human readable list of families this drivers supports */ -static const char *device_families = "STM32L4/L4+/WB/WL/G4/G0"; +/* human readable list of families this drivers supports (sorted alphabetically) */ +static const char *device_families = "STM32G0/G4/L4/L4+/WB/WL"; static const struct stm32l4_rev stm32_415_revs[] = { { 0x1000, "1" }, { 0x1001, "2" }, { 0x1003, "3" }, { 0x1007, "4" } @@ -211,6 +238,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 1024, .has_dual_bank = true, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -221,6 +249,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 256, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -231,6 +260,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 128, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -241,6 +271,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 1024, .has_dual_bank = true, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -251,6 +282,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 512, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -261,6 +293,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 128, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -271,6 +304,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 64, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -281,6 +315,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 128, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -291,6 +326,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 512, .has_dual_bank = true, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -301,6 +337,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 2048, .has_dual_bank = true, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -311,6 +348,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 1024, .has_dual_bank = true, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -321,6 +359,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 512, .has_dual_bank = false, .flash_regs_base = 0x40022000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -331,6 +370,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 1024, .has_dual_bank = false, .flash_regs_base = 0x58004000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -341,6 +381,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 512, .has_dual_bank = false, .flash_regs_base = 0x58004000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, { @@ -351,6 +392,7 @@ static const struct stm32l4_part_info stm32l4_parts[] = { .max_flash_size_kb = 256, .has_dual_bank = false, .flash_regs_base = 0x58004000, + .default_flash_regs = stm32l4_flash_regs, .fsize_addr = 0x1FFF75E0, }, }; @@ -384,16 +426,37 @@ static inline uint32_t stm32l4_get_flash_reg(struct flash_bank *bank, uint32_t r return stm32l4_info->part_info->flash_regs_base + reg_offset; } +static inline uint32_t stm32l4_get_flash_reg_by_index(struct flash_bank *bank, + enum stm32l4_flash_reg_index reg_index) +{ + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + return stm32l4_get_flash_reg(bank, stm32l4_info->flash_regs[reg_index]); +} + static inline int stm32l4_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value) { return target_read_u32(bank->target, stm32l4_get_flash_reg(bank, reg_offset), value); } +static inline int stm32l4_read_flash_reg_by_index(struct flash_bank *bank, + enum stm32l4_flash_reg_index reg_index, uint32_t *value) +{ + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + return stm32l4_read_flash_reg(bank, stm32l4_info->flash_regs[reg_index], value); +} + static inline int stm32l4_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value) { return target_write_u32(bank->target, stm32l4_get_flash_reg(bank, reg_offset), value); } +static inline int stm32l4_write_flash_reg_by_index(struct flash_bank *bank, + enum stm32l4_flash_reg_index reg_index, uint32_t value) +{ + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + return stm32l4_write_flash_reg(bank, stm32l4_info->flash_regs[reg_index], value); +} + static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) { uint32_t status; @@ -401,7 +464,7 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) /* wait for busy to clear */ for (;;) { - retval = stm32l4_read_flash_reg(bank, STM32_FLASH_SR, &status); + retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, &status); if (retval != ERROR_OK) return retval; LOG_DEBUG("status: 0x%" PRIx32 "", status); @@ -427,7 +490,7 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) /* If this operation fails, we ignore it and report the original * retval */ - stm32l4_write_flash_reg(bank, STM32_FLASH_SR, status & FLASH_ERROR); + stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, status & FLASH_ERROR); } return retval; @@ -440,7 +503,7 @@ static int stm32l4_unlock_reg(struct flash_bank *bank) /* first check if not already unlocked * otherwise writing on STM32_FLASH_KEYR will fail */ - int retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); + int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl); if (retval != ERROR_OK) return retval; @@ -448,15 +511,15 @@ static int stm32l4_unlock_reg(struct flash_bank *bank) return ERROR_OK; /* unlock flash registers */ - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_KEYR, KEY1); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_KEYR_INDEX, KEY1); if (retval != ERROR_OK) return retval; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_KEYR, KEY2); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_KEYR_INDEX, KEY2); if (retval != ERROR_OK) return retval; - retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); + retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl); if (retval != ERROR_OK) return retval; @@ -472,7 +535,7 @@ static int stm32l4_unlock_option_reg(struct flash_bank *bank) { uint32_t ctrl; - int retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); + int retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl); if (retval != ERROR_OK) return retval; @@ -480,15 +543,15 @@ static int stm32l4_unlock_option_reg(struct flash_bank *bank) return ERROR_OK; /* unlock option registers */ - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_OPTKEYR, OPTKEY1); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_OPTKEYR_INDEX, OPTKEY1); if (retval != ERROR_OK) return retval; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_OPTKEYR, OPTKEY2); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_OPTKEYR_INDEX, OPTKEY2); if (retval != ERROR_OK) return retval; - retval = stm32l4_read_flash_reg(bank, STM32_FLASH_CR, &ctrl); + retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, &ctrl); if (retval != ERROR_OK) return retval; @@ -524,14 +587,14 @@ static int stm32l4_write_option(struct flash_bank *bank, uint32_t reg_offset, if (retval != ERROR_OK) goto err_lock; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_OPTSTRT); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_OPTSTRT); if (retval != ERROR_OK) goto err_lock; retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); err_lock: - retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK | FLASH_OPTLOCK); + retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK | FLASH_OPTLOCK); if (retval != ERROR_OK) return retval; @@ -544,11 +607,11 @@ static int stm32l4_protect_check(struct flash_bank *bank) struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; uint32_t wrp1ar, wrp1br, wrp2ar, wrp2br; - stm32l4_read_flash_reg(bank, STM32_FLASH_WRP1AR, &wrp1ar); - stm32l4_read_flash_reg(bank, STM32_FLASH_WRP1BR, &wrp1br); + stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_WRP1AR_INDEX, &wrp1ar); + stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_WRP1BR_INDEX, &wrp1br); if (stm32l4_info->part_info->has_dual_bank) { - stm32l4_read_flash_reg(bank, STM32_FLASH_WRP2AR, &wrp2ar); - stm32l4_read_flash_reg(bank, STM32_FLASH_WRP2BR, &wrp2br); + stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_WRP2AR_INDEX, &wrp2ar); + stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_WRP2BR_INDEX, &wrp2br); } else { /* prevent uninitialized errors */ wrp2ar = 0; @@ -627,7 +690,7 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first, erase_flags |= snb << FLASH_PAGE_SHIFT | FLASH_CR_BKER; } else erase_flags |= i << FLASH_PAGE_SHIFT; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, erase_flags); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, erase_flags); if (retval != ERROR_OK) break; @@ -639,7 +702,7 @@ static int stm32l4_erase(struct flash_bank *bank, unsigned int first, } err_lock: - retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); + retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK); if (retval != ERROR_OK) return retval; @@ -667,7 +730,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, reg_value = ((last & 0xFF) << 16) | begin; } - ret = stm32l4_write_option(bank, STM32_FLASH_WRP2AR, reg_value, 0xffffffff); + ret = stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_WRP2AR_INDEX], reg_value, 0xffffffff); } /* Bank 1 */ reg_value = 0xFF; /* Default to bank un-protected */ @@ -677,7 +740,7 @@ static int stm32l4_protect(struct flash_bank *bank, int set, unsigned int first, reg_value = (end << 16) | (first & 0xFF); } - ret = stm32l4_write_option(bank, STM32_FLASH_WRP1AR, reg_value, 0xffffffff); + ret = stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_WRP1AR_INDEX], reg_value, 0xffffffff); } return ret; @@ -743,8 +806,8 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size); buf_set_u32(reg_params[2].value, 0, 32, address); buf_set_u32(reg_params[3].value, 0, 32, count); - buf_set_u32(reg_params[4].value, 0, 32, stm32l4_get_flash_reg(bank, STM32_FLASH_SR)); - buf_set_u32(reg_params[5].value, 0, 32, stm32l4_get_flash_reg(bank, STM32_FLASH_CR)); + buf_set_u32(reg_params[4].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX)); + buf_set_u32(reg_params[5].value, 0, 32, stm32l4_get_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX)); retval = target_run_flash_async_algorithm(target, buffer, count, 8, 0, NULL, @@ -764,7 +827,7 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, if (error != 0) { LOG_ERROR("flash write failed = %08" PRIx32, error); /* Clear but report errors */ - stm32l4_write_flash_reg(bank, STM32_FLASH_SR, error); + stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_SR_INDEX, error); retval = ERROR_FAIL; } } @@ -841,7 +904,7 @@ static int stm32l4_write(struct flash_bank *bank, const uint8_t *buffer, retval = stm32l4_write_block(bank, buffer, offset, count / 8); err_lock: - retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); + retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK); if (retval != ERROR_OK) { LOG_ERROR("block write failed"); @@ -896,6 +959,7 @@ static int stm32l4_probe(struct flash_bank *bank) } part_info = stm32l4_info->part_info; + stm32l4_info->flash_regs = stm32l4_info->part_info->default_flash_regs; char device_info[1024]; retval = bank->driver->info(bank, device_info, sizeof(device_info)); @@ -929,7 +993,7 @@ static int stm32l4_probe(struct flash_bank *bank) assert((flash_size_kb != 0xffff) && flash_size_kb); /* read flash option register */ - retval = stm32l4_read_flash_reg(bank, STM32_FLASH_OPTR, &options); + retval = stm32l4_read_flash_reg_by_index(bank, STM32_FLASH_OPTR_INDEX, &options); if (retval != ERROR_OK) return retval; @@ -1150,18 +1214,18 @@ static int stm32l4_mass_erase(struct flash_bank *bank) if (retval != ERROR_OK) goto err_lock; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, action); if (retval != ERROR_OK) goto err_lock; - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, action | FLASH_STRT); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, action | FLASH_STRT); if (retval != ERROR_OK) goto err_lock; retval = stm32l4_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); err_lock: - retval2 = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_LOCK); + retval2 = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_LOCK); if (retval != ERROR_OK) return retval; @@ -1274,7 +1338,7 @@ COMMAND_HANDLER(stm32l4_handle_option_load_command) * "Note: If the read protection is set while the debugger is still * connected through JTAG/SWD, apply a POR (power-on reset) instead of a system reset." */ - retval = stm32l4_write_flash_reg(bank, STM32_FLASH_CR, FLASH_OBL_LAUNCH); + retval = stm32l4_write_flash_reg_by_index(bank, STM32_FLASH_CR_INDEX, FLASH_OBL_LAUNCH); command_print(CMD, "stm32l4x option load completed. Power-on reset might be required"); @@ -1305,7 +1369,8 @@ COMMAND_HANDLER(stm32l4_handle_lock_command) } /* set readout protection level 1 by erasing the RDP option byte */ - if (stm32l4_write_option(bank, STM32_FLASH_OPTR, 0, 0x000000FF) != ERROR_OK) { + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + if (stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_OPTR_INDEX], 0, 0x000000FF) != ERROR_OK) { command_print(CMD, "%s failed to lock device", bank->driver->name); return ERROR_OK; } @@ -1332,7 +1397,9 @@ COMMAND_HANDLER(stm32l4_handle_unlock_command) return ERROR_TARGET_NOT_HALTED; } - if (stm32l4_write_option(bank, STM32_FLASH_OPTR, RDP_LEVEL_0, 0x000000FF) != ERROR_OK) { + struct stm32l4_flash_bank *stm32l4_info = bank->driver_priv; + if (stm32l4_write_option(bank, stm32l4_info->flash_regs[STM32_FLASH_OPTR_INDEX], + RDP_LEVEL_0, 0x000000FF) != ERROR_OK) { command_print(CMD, "%s failed to unlock device", bank->driver->name); return ERROR_OK; } diff --git a/src/flash/nor/stm32l4x.h b/src/flash/nor/stm32l4x.h index abd8010fc..3e810a03c 100644 --- a/src/flash/nor/stm32l4x.h +++ b/src/flash/nor/stm32l4x.h @@ -19,18 +19,6 @@ #ifndef OPENOCD_FLASH_NOR_STM32L4X #define OPENOCD_FLASH_NOR_STM32L4X -/* Flash registers offsets */ -#define STM32_FLASH_ACR 0x00 -#define STM32_FLASH_KEYR 0x08 -#define STM32_FLASH_OPTKEYR 0x0c -#define STM32_FLASH_SR 0x10 -#define STM32_FLASH_CR 0x14 -#define STM32_FLASH_OPTR 0x20 -#define STM32_FLASH_WRP1AR 0x2c -#define STM32_FLASH_WRP1BR 0x30 -#define STM32_FLASH_WRP2AR 0x4c -#define STM32_FLASH_WRP2BR 0x50 - /* FLASH_CR register bits */ #define FLASH_PG (1 << 0) #define FLASH_PER (1 << 1) ----------------------------------------------------------------------- Summary of changes: src/flash/nor/stm32l4x.c | 141 ++++++++++++++++++++++++++++++++++------------- src/flash/nor/stm32l4x.h | 12 ---- 2 files changed, 104 insertions(+), 49 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:40:06
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 44cf202ef585ea5e2dda78e65cc5d04e08129eff (commit) via 0e0283e582ddc06b34f3d7e3b09d1754dd501794 (commit) via 9c314578750324b8d46cdbe0801d3cdfc25c4a4c (commit) from e6770f1ab6b9a34dbe90d3fa6ae4093914a0d707 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 44cf202ef585ea5e2dda78e65cc5d04e08129eff Author: Tarek BOCHKATI <tar...@st...> Date: Fri Nov 6 12:33:14 2020 +0100 60-openocd.rules: add ULINKplus CMSIS-DAP based adapter Change-Id: I5935e0a184b8995122d197046ef8fb4e7eefb884 Signed-off-by: Tarek BOCHKATI <tar...@st...> Reviewed-on: http://openocd.zylin.com/5926 Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> Tested-by: jenkins diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index 53f97dd83..fe57364d7 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -167,6 +167,7 @@ ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", # Keil Software, Inc. ULink ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2750", MODE="660", GROUP="plugdev", TAG+="uaccess" # CMSIS-DAP compatible adapters ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess" commit 0e0283e582ddc06b34f3d7e3b09d1754dd501794 Author: Tomas Vanek <va...@fb...> Date: Sun Nov 8 22:34:26 2020 +0100 doc: document CMSIS-DAP v2 Change-Id: Ie54e855901c079b456c26a6239177c7678cdcac7 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5930 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/doc/openocd.texi b/doc/openocd.texi index 84ed32060..292bbd77c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2429,7 +2429,8 @@ and a specific set of GPIOs is used. @end deffn @deffn {Interface Driver} {cmsis-dap} -ARM CMSIS-DAP compliant based adapter. +ARM CMSIS-DAP compliant based adapter v1 (USB HID based) +or v2 (USB bulk). @deffn {Config Command} {cmsis_dap_vid_pid} [vid pid]+ The vendor ID and product ID of the CMSIS-DAP device. If not specified @@ -2445,6 +2446,23 @@ Specifies the @var{serial} of the CMSIS-DAP device to use. If not specified, serial numbers are not considered. @end deffn +@deffn {Config Command} {cmsis_dap_backend} [@option{auto}|@option{usb_bulk}|@option{hid}] +Specifies how to communicate with the adapter: + +@itemize @minus +@item @option{hid} Use HID generic reports - CMSIS-DAP v1 +@item @option{usb_bulk} Use USB bulk - CMSIS-DAP v2 +@item @option{auto} First try USB bulk CMSIS-DAP v2, if not found try HID CMSIS-DAP v1. +This is the default if @command{cmsis_dap_backend} is not specified. +@end itemize +@end deffn + +@deffn {Config Command} {cmsis_dap_usb interface} [number] +Specifies the @var{number} of the USB interface to use in v2 mode (USB bulk). +In most cases need not to be specified and interfaces are searched by +interface string or for user class interface. +@end deffn + @deffn {Command} {cmsis-dap info} Display various device information, like hardware version, firmware version, current bus status. @end deffn commit 9c314578750324b8d46cdbe0801d3cdfc25c4a4c Author: Antonio Borneo <bor...@gm...> Date: Thu Jul 30 21:36:39 2020 +0200 jtag/drivers/cmsis_dap: fix build with gcc 10.1.0 Avoid multiple definition of cmsis_dap_usb_backend and cmsis_dap_hid_backend using 'extern'. Move the prototypes in cmsis_dap.h. Remove the useless #if/#endif around the prototypes. Change-Id: I8d73fe148e2155620244bc887d4235e9af530e30 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5790 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/drivers/cmsis_dap.c b/src/jtag/drivers/cmsis_dap.c index 8ddb54179..16480ae1e 100644 --- a/src/jtag/drivers/cmsis_dap.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -43,15 +43,6 @@ #include "cmsis_dap.h" -#if BUILD_CMSIS_DAP_USB == 1 -const struct cmsis_dap_backend cmsis_dap_usb_backend; -extern const struct command_registration cmsis_dap_usb_subcommand_handlers[]; -#endif - -#if BUILD_CMSIS_DAP_HID == 1 -const struct cmsis_dap_backend cmsis_dap_hid_backend; -#endif - static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { #if BUILD_CMSIS_DAP_USB == 1 &cmsis_dap_usb_backend, diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h index 8cbb8dd07..054621cd5 100644 --- a/src/jtag/drivers/cmsis_dap.h +++ b/src/jtag/drivers/cmsis_dap.h @@ -25,4 +25,8 @@ struct cmsis_dap_backend { int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); }; +extern const struct cmsis_dap_backend cmsis_dap_hid_backend; +extern const struct cmsis_dap_backend cmsis_dap_usb_backend; +extern const struct command_registration cmsis_dap_usb_subcommand_handlers[]; + #endif ----------------------------------------------------------------------- Summary of changes: contrib/60-openocd.rules | 1 + doc/openocd.texi | 20 +++++++++++++++++++- src/jtag/drivers/cmsis_dap.c | 9 --------- src/jtag/drivers/cmsis_dap.h | 4 ++++ 4 files changed, 24 insertions(+), 10 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:39:06
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via e6770f1ab6b9a34dbe90d3fa6ae4093914a0d707 (commit) from 8f927d51643ceb6b3696772c5fabd5ba9f48fcd3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e6770f1ab6b9a34dbe90d3fa6ae4093914a0d707 Author: Tomas Vanek <va...@fb...> Date: Thu Jul 30 10:26:34 2020 +0200 jtag/drivers/cmsis_dap: fix usb bulk connection logic http://openocd.zylin.com/4831 has following problems in selecting USB device/interface to connect: - attempts connection to any device with user class and 2 bulk endpoints - regardless of cmsis_dap_vid_pid or cmsis_dap_serial setting connects to the first suitable device Distinguish between real match and no filtering cases and use that info appropriately. Add debug messages to show why the interface is refused. Move CMSIS-DAP interface string detection before checking of class/endpoints to give more understandable debug log in the case the device is refused. Keep track of reliable matches in both device and interface enumeration. First search for the interface with CMSIS-DAP in the interface string. If it fails, chose the first suitable interface. Change-Id: Ia1aacd5631a9f5c5db580bfb5745ceb6240d61ad Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5789 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c index b82e3dae5..0134c0376 100644 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -81,7 +81,8 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p /* Match VID/PID */ - bool id_match = true; /* match if we don't enter the loop (no filter) */ + bool id_match = false; + bool id_filter = vids[0] || pids[0]; for (int id = 0; vids[id] || pids[id]; id++) { id_match = !vids[id] || dev_desc.idVendor == vids[id]; id_match &= !pids[id] || dev_desc.idProduct == pids[id]; @@ -90,7 +91,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p break; } - if (!id_match) + if (id_filter && !id_match) continue; /* Don't continue if we asked for a serial number and the device doesn't have one */ @@ -103,7 +104,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p /* It's to be expected that most USB devices can't be opened * so only report an error if it was explicitly selected */ - if (vids[0] || pids[0]) { + if (id_filter) { LOG_ERROR("could not open device 0x%04x:0x%04x: %s", dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); } else { @@ -115,7 +116,7 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p /* Match serial number */ - bool serial_match = (serial == NULL); + bool serial_match = false; char dev_serial[256] = {0}; if (dev_desc.iSerialNumber > 0) { err = libusb_get_string_descriptor_ascii( @@ -123,35 +124,44 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p (uint8_t *)dev_serial, sizeof(dev_serial)); if (err < 0) { - LOG_ERROR("could not read serial number for device 0x%04x:0x%04x: %s", - dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + const char *msg = "could not read serial number for device 0x%04x:0x%04x: %s"; + if (serial) + LOG_WARNING(msg, dev_desc.idVendor, dev_desc.idProduct, + libusb_strerror(err)); + else + LOG_DEBUG(msg, dev_desc.idVendor, dev_desc.idProduct, + libusb_strerror(err)); } else if (serial && strncmp(dev_serial, serial, sizeof(dev_serial)) == 0) { serial_match = true; } } - if (!serial_match) { + if (serial && !serial_match) { libusb_close(dev_handle); continue; } /* Find the CMSIS-DAP string in product string */ - bool cmsis_dap_found = false; + bool cmsis_dap_in_product_str = false; char product_string[256] = {0}; if (dev_desc.iProduct > 0) { err = libusb_get_string_descriptor_ascii( dev_handle, dev_desc.iProduct, (uint8_t *)product_string, sizeof(product_string)); if (err < 0) { - LOG_ERROR("could not read product string for device 0x%04x:0x%04x: %s", + LOG_WARNING("could not read product string for device 0x%04x:0x%04x: %s", dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); } else if (strstr(product_string, "CMSIS-DAP")) { - LOG_DEBUG("CMSIS-DAP found in product string"); - cmsis_dap_found = true; + LOG_DEBUG("found product string of 0x%04x:0x%04x '%s'", + dev_desc.idVendor, dev_desc.idProduct, product_string); + cmsis_dap_in_product_str = true; } } + bool device_identified_reliably = cmsis_dap_in_product_str + || serial_match || id_match; + /* Find the CMSIS-DAP interface */ for (int config = 0; config < dev_desc.bNumConfigurations; config++) { @@ -163,7 +173,11 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p continue; } + LOG_DEBUG("enumerating interfaces of 0x%04x:0x%04x", + dev_desc.idVendor, dev_desc.idProduct); int config_num = config_desc->bConfigurationValue; + const struct libusb_interface_descriptor *intf_desc_candidate = NULL; + const struct libusb_interface_descriptor *intf_desc_found = NULL; for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; @@ -190,98 +204,165 @@ static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t p * - Endpoint 3: Bulk In (optional) â used for streaming SWO trace (if enabled with SWO_STREAM). */ - if (intf_desc->bNumEndpoints < 2) + /* Search for "CMSIS-DAP" in the interface string */ + bool cmsis_dap_in_interface_str = false; + if (intf_desc->iInterface != 0) { + + char interface_str[256] = {0}; + + err = libusb_get_string_descriptor_ascii( + dev_handle, intf_desc->iInterface, + (uint8_t *)interface_str, sizeof(interface_str)); + if (err < 0) { + LOG_DEBUG("could not read interface string %d for device 0x%04x:0x%04x: %s", + intf_desc->iInterface, + dev_desc.idVendor, dev_desc.idProduct, + libusb_strerror(err)); + } else if (strstr(interface_str, "CMSIS-DAP")) { + cmsis_dap_in_interface_str = true; + LOG_DEBUG("found interface %d string '%s'", + interface_num, interface_str); + } + } + + /* Bypass the following check if this interface was explicitly requested. */ + if (cmsis_dap_usb_interface == -1) { + if (!cmsis_dap_in_product_str && !cmsis_dap_in_interface_str) + continue; + } + + /* check endpoints */ + if (intf_desc->bNumEndpoints < 2) { + LOG_DEBUG("skipping interface %d, has only %d endpoints", + interface_num, intf_desc->bNumEndpoints); continue; + } if ((intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || - (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT) + (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT) { + LOG_DEBUG("skipping interface %d, endpoint[0] is not bulk out", + interface_num); continue; + } if ((intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || - (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) + (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) { + LOG_DEBUG("skipping interface %d, endpoint[1] is not bulk in", + interface_num); continue; + } - /* Bypass the following checks if this interface was explicitly requested. */ - if (cmsis_dap_usb_interface == -1) { - if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC || - intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) + /* We can rely on the interface is really CMSIS-DAP if + * - we've seen CMSIS-DAP in the interface string + * - config asked explicitly for an interface number + * - the device has only one interface + * The later two cases should be honored only if we know + * we are on the rigt device */ + bool intf_identified_reliably = cmsis_dap_in_interface_str + || (device_identified_reliably && + (cmsis_dap_usb_interface != -1 + || config_desc->bNumInterfaces == 1)); + + if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC || + intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) { + /* If the interface is reliably identified + * then we need not insist on setting USB class, subclass and protocol + * exactly as the specification requires. + * At least KitProg3 uses class 0 contrary to the specification */ + if (intf_identified_reliably) { + LOG_WARNING("Using CMSIS-DAPv2 interface %d with wrong class %" PRId8 + " subclass %" PRId8 " or protocol %" PRId8, + interface_num, + intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass, + intf_desc->bInterfaceProtocol); + } else { + LOG_DEBUG("skipping interface %d, class %" PRId8 + " subclass %" PRId8 " protocol %" PRId8, + interface_num, + intf_desc->bInterfaceClass, + intf_desc->bInterfaceSubClass, + intf_desc->bInterfaceProtocol); continue; - /* Search for "CMSIS-DAP" in the interface string */ - if (cmsis_dap_usb_interface != -1 && !cmsis_dap_found) { - if (intf_desc->iInterface == 0) - continue; - - char interface_str[256] = {0}; - - err = libusb_get_string_descriptor_ascii( - dev_handle, intf_desc->iInterface, - (uint8_t *)interface_str, sizeof(interface_str)); - if (err < 0) { - LOG_ERROR("could not read interface string for device 0x%04x:0x%04x: %s", - dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); - continue; - } else if (!strstr(interface_str, "CMSIS-DAP")) { - continue; - } else { - LOG_DEBUG("CMSIS-DAP found in interface string"); - } } } - int packet_size = intf_desc->endpoint[0].wMaxPacketSize; - int ep_out = intf_desc->endpoint[0].bEndpointAddress; - int ep_in = intf_desc->endpoint[1].bEndpointAddress; + if (intf_identified_reliably) { + /* That's the one! */ + intf_desc_found = intf_desc; + break; + } + + if (!intf_desc_candidate && device_identified_reliably) { + /* This interface looks suitable for CMSIS-DAP. Store the pointer to it + * and keep searching for another one with CMSIS-DAP in interface string */ + intf_desc_candidate = intf_desc; + } + } + + if (!intf_desc_found) { + /* We were not able to identify reliably which interface is CMSIS-DAP. + * Let's use the first suitable if we found one */ + intf_desc_found = intf_desc_candidate; + } - /* That's the one! */ + if (!intf_desc_found) { libusb_free_config_descriptor(config_desc); - libusb_free_device_list(device_list, true); + continue; + } - LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s", - dev_desc.idVendor, dev_desc.idProduct, dev_serial); + /* We've chosen an interface, connect to it */ + int interface_num = intf_desc_found->bInterfaceNumber; + int packet_size = intf_desc_found->endpoint[0].wMaxPacketSize; + int ep_out = intf_desc_found->endpoint[0].bEndpointAddress; + int ep_in = intf_desc_found->endpoint[1].bEndpointAddress; - int current_config; - err = libusb_get_configuration(dev_handle, ¤t_config); - if (err) { - LOG_ERROR("could not find current configuration: %s", libusb_strerror(err)); - libusb_close(dev_handle); - libusb_exit(ctx); - return ERROR_FAIL; - } + libusb_free_config_descriptor(config_desc); + libusb_free_device_list(device_list, true); - if (config_num != current_config) { - err = libusb_set_configuration(dev_handle, config_num); - if (err) { - LOG_ERROR("could not set configuration: %s", libusb_strerror(err)); - libusb_close(dev_handle); - libusb_exit(ctx); - return ERROR_FAIL; - } - } + LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s", + dev_desc.idVendor, dev_desc.idProduct, dev_serial); - err = libusb_claim_interface(dev_handle, interface_num); - if (err) - LOG_WARNING("could not claim interface: %s", libusb_strerror(err)); + int current_config; + err = libusb_get_configuration(dev_handle, ¤t_config); + if (err) { + LOG_ERROR("could not find current configuration: %s", libusb_strerror(err)); + libusb_close(dev_handle); + libusb_exit(ctx); + return ERROR_FAIL; + } - dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); - if (dap->bdata == NULL) { - LOG_ERROR("unable to allocate memory"); - libusb_release_interface(dev_handle, interface_num); + if (config_num != current_config) { + err = libusb_set_configuration(dev_handle, config_num); + if (err) { + LOG_ERROR("could not set configuration: %s", libusb_strerror(err)); libusb_close(dev_handle); libusb_exit(ctx); return ERROR_FAIL; } + } - dap->packet_size = packet_size + 1; /* "+ 1" for compatibility with the HID backend */ - dap->bdata->usb_ctx = ctx; - dap->bdata->dev_handle = dev_handle; - dap->bdata->ep_out = ep_out; - dap->bdata->ep_in = ep_in; - dap->bdata->interface = interface_num; - return ERROR_OK; + err = libusb_claim_interface(dev_handle, interface_num); + if (err) + LOG_WARNING("could not claim interface: %s", libusb_strerror(err)); + + dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); + if (dap->bdata == NULL) { + LOG_ERROR("unable to allocate memory"); + libusb_release_interface(dev_handle, interface_num); + libusb_close(dev_handle); + libusb_exit(ctx); + return ERROR_FAIL; } - libusb_free_config_descriptor(config_desc); + dap->packet_size = packet_size + 1; /* "+ 1" for compatibility with the HID backend */ + dap->bdata->usb_ctx = ctx; + dap->bdata->dev_handle = dev_handle; + dap->bdata->ep_out = ep_out; + dap->bdata->ep_in = ep_in; + dap->bdata->interface = interface_num; + return ERROR_OK; } libusb_close(dev_handle); ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/cmsis_dap_usb_bulk.c | 233 +++++++++++++++++++++++----------- 1 file changed, 157 insertions(+), 76 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:38:05
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 8f927d51643ceb6b3696772c5fabd5ba9f48fcd3 (commit) from b1f488ec1ea4c8b5410026610c621f85b5ff17f3 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 8f927d51643ceb6b3696772c5fabd5ba9f48fcd3 Author: Mickaël Thomas <mic...@gm...> Date: Tue Jan 29 21:14:58 2019 +0100 Add CMSIS-DAP v2 support This change implements CMSIS-DAP v2 which works with raw USB bulk transfers. The old driver is now split into a generic CMSIS part and a HID backend, with a new raw USB backend for CMSIS-DAP v2. New commands: - cmsis_dap_backend (usb_bulk | hid | auto) - cmsis_dap_usb interface <interface number> Change-Id: I4218477b12ccbfe19c9b332321cd21394bf44e30 Signed-off-by: Mickaël Thomas <mic...@gm...> Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/4831 Tested-by: jenkins diff --git a/configure.ac b/configure.ac index 3e49213cc..9cb20ad89 100644 --- a/configure.ac +++ b/configure.ac @@ -119,6 +119,7 @@ m4_define([USB1_ADAPTERS], [[ft232r], [Bitbang mode of FT232R based devices], [FT232R]], [[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]], [[xds110], [TI XDS110 Debug Probe], [XDS110]], + [[cmsis_dap_v2], [CMSIS-DAP v2 Compliant Debugger], [CMSIS_DAP_USB]], [[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]], [[opendous], [eStick/opendous JTAG Programmer], [OPENDOUS]], [[aice], [Andes JTAG Programmer], [AICE]]]) @@ -129,7 +130,7 @@ m4_define([USB0_ADAPTERS], [[armjtagew], [Olimex ARM-JTAG-EW Programmer], [ARMJTAGEW]]]) m4_define([HIDAPI_ADAPTERS], - [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]], + [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP_HID]], [[nulink], [Nu-Link Programmer], [HLADAPTER_NULINK]]]) m4_define([HIDAPI_USB1_ADAPTERS], diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 1a5ab4a2d..f7a54b003 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -170,8 +170,15 @@ endif if OPENJTAG DRIVERFILES += %D%/openjtag.c endif -if CMSIS_DAP -DRIVERFILES += %D%/cmsis_dap_usb.c +if CMSIS_DAP_HID +DRIVERFILES += %D%/cmsis_dap_usb_hid.c +DRIVERFILES += %D%/cmsis_dap.c +endif +if CMSIS_DAP_USB +DRIVERFILES += %D%/cmsis_dap_usb_bulk.c +if !CMSIS_DAP_HID +DRIVERFILES += %D%/cmsis_dap.c +endif endif if IMX_GPIO DRIVERFILES += %D%/imx_gpio.c @@ -189,6 +196,7 @@ DRIVERHEADERS = \ %D%/jtag_usb_common.h \ %D%/libftdi_helper.h \ %D%/libusb_helper.h \ + %D%/cmsis_dap.h \ %D%/minidriver_imp.h \ %D%/mpsse.h \ %D%/rlink.h \ diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap.c similarity index 88% rename from src/jtag/drivers/cmsis_dap_usb.c rename to src/jtag/drivers/cmsis_dap.c index 6d55392d5..8ddb54179 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap.c @@ -1,4 +1,7 @@ /*************************************************************************** + * Copyright (C) 2018 by Mickaël Thomas * + * mic...@gm... * + * * * Copyright (C) 2016 by Maksym Hilliaka * * ot...@fr... * * * @@ -38,12 +41,26 @@ #include <jtag/commands.h> #include <jtag/tcl.h> -#include <hidapi.h> +#include "cmsis_dap.h" -/* - * See CMSIS-DAP documentation: - * Version 0.01 - Beta. - */ +#if BUILD_CMSIS_DAP_USB == 1 +const struct cmsis_dap_backend cmsis_dap_usb_backend; +extern const struct command_registration cmsis_dap_usb_subcommand_handlers[]; +#endif + +#if BUILD_CMSIS_DAP_HID == 1 +const struct cmsis_dap_backend cmsis_dap_hid_backend; +#endif + +static const struct cmsis_dap_backend *const cmsis_dap_backends[] = { +#if BUILD_CMSIS_DAP_USB == 1 + &cmsis_dap_usb_backend, +#endif + +#if BUILD_CMSIS_DAP_HID == 1 + &cmsis_dap_hid_backend, +#endif +}; /* USB Config */ @@ -52,6 +69,7 @@ * PID 0xf001: LPC-Link-II CMSIS_DAP * PID 0xf002: OPEN-SDA CMSIS_DAP (Freedom Board) * PID 0x2722: Keil ULINK2 CMSIS-DAP + * PID 0x2750: Keil ULINKplus CMSIS-DAP * * VID 0x0d28: mbed Software * PID 0x0204: MBED CMSIS-DAP @@ -61,10 +79,10 @@ /* vid = pid = 0 marks the end of the list */ static uint16_t cmsis_dap_vid[MAX_USB_IDS + 1] = { 0 }; static uint16_t cmsis_dap_pid[MAX_USB_IDS + 1] = { 0 }; -static wchar_t *cmsis_dap_serial; +static char *cmsis_dap_serial; +static int cmsis_dap_backend = -1; static bool swd_mode; -#define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */ #define USB_TIMEOUT 1000 /* CMSIS-DAP General Commands */ @@ -163,14 +181,6 @@ static const char * const info_caps_str[] = { /* max clock speed (kHz) */ #define DAP_MAX_CLOCK 5000 -struct cmsis_dap { - hid_device *dev_handle; - uint16_t packet_size; - int packet_count; - uint8_t *packet_buffer; - uint8_t caps; - uint8_t mode; -}; struct pending_transfer_result { uint8_t cmd; @@ -223,134 +233,66 @@ static uint8_t output_pins = SWJ_PIN_SRST | SWJ_PIN_TRST; static struct cmsis_dap *cmsis_dap_handle; -static int cmsis_dap_usb_open(void) -{ - hid_device *dev = NULL; - int i; - struct hid_device_info *devs, *cur_dev; - unsigned short target_vid, target_pid; - bool found = false; - target_vid = 0; - target_pid = 0; +static int cmsis_dap_open(void) +{ + const struct cmsis_dap_backend *backend = NULL; - if (hid_init() != 0) { - LOG_ERROR("unable to open HIDAPI"); + struct cmsis_dap *dap = malloc(sizeof(struct cmsis_dap)); + if (dap == NULL) { + LOG_ERROR("unable to allocate memory"); return ERROR_FAIL; } - /* - * The CMSIS-DAP specification stipulates: - * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the - * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer." - */ - devs = hid_enumerate(0x0, 0x0); - cur_dev = devs; - while (NULL != cur_dev) { - if (0 == cmsis_dap_vid[0]) { - if (NULL == cur_dev->product_string) { - LOG_DEBUG("Cannot read product string of device 0x%x:0x%x", - cur_dev->vendor_id, cur_dev->product_id); - } else { - if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) { - /* if the user hasn't specified VID:PID *and* - * product string contains "CMSIS-DAP", pick it - */ - found = true; - } - } - } else { - /* otherwise, exhaustively compare against all VID:PID in list */ - for (i = 0; cmsis_dap_vid[i] || cmsis_dap_pid[i]; i++) { - if ((cmsis_dap_vid[i] == cur_dev->vendor_id) && (cmsis_dap_pid[i] == cur_dev->product_id)) - found = true; - } - - if (cmsis_dap_vid[i] || cmsis_dap_pid[i]) - found = true; - } - - /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */ - if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0) - found = false; + dap->caps = 0; + dap->mode = 0; + dap->packet_size = 0; /* initialized by backend */ - if (found) { - /* we have found an adapter, so exit further checks */ - /* check serial number matches if given */ - if (cmsis_dap_serial != NULL) { - if ((cur_dev->serial_number != NULL) && wcscmp(cmsis_dap_serial, cur_dev->serial_number) == 0) { - break; - } - } else + if (cmsis_dap_backend >= 0) { + /* Use forced backend */ + backend = cmsis_dap_backends[cmsis_dap_backend]; + if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) != ERROR_OK) + backend = NULL; + } else { + /* Try all backends */ + for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { + backend = cmsis_dap_backends[i]; + if (backend->open(dap, cmsis_dap_vid, cmsis_dap_pid, cmsis_dap_serial) == ERROR_OK) break; - - found = false; + else + backend = NULL; } - - cur_dev = cur_dev->next; - } - - if (NULL != cur_dev) { - target_vid = cur_dev->vendor_id; - target_pid = cur_dev->product_id; } - if (target_vid == 0 && target_pid == 0) { - LOG_ERROR("unable to find CMSIS-DAP device"); - hid_free_enumeration(devs); + if (backend == NULL) { + LOG_ERROR("unable to find a matching CMSIS-DAP device"); + free(dap); return ERROR_FAIL; } - dev = hid_open_path(cur_dev->path); - hid_free_enumeration(devs); + assert(dap->packet_size > 0); - if (dev == NULL) { - LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid); - return ERROR_FAIL; - } + dap->backend = backend; + dap->packet_buffer = malloc(dap->packet_size); - struct cmsis_dap *dap = malloc(sizeof(struct cmsis_dap)); - if (dap == NULL) { + if (dap->packet_buffer == NULL) { LOG_ERROR("unable to allocate memory"); + dap->backend->close(dap); + free(dap); return ERROR_FAIL; } - dap->dev_handle = dev; - dap->caps = 0; - dap->mode = 0; - cmsis_dap_handle = dap; - /* allocate default packet buffer, may be changed later. - * currently with HIDAPI we have no way of getting the output report length - * without this info we cannot communicate with the adapter. - * For the moment we ahve to hard code the packet size */ - - int packet_size = PACKET_SIZE; - - /* atmel cmsis-dap uses 512 byte reports */ - /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained - * board */ - /* TODO: HID report descriptor should be parsed instead of - * hardcoding a match by VID */ - if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175) - packet_size = 512 + 1; - - cmsis_dap_handle->packet_buffer = malloc(packet_size); - cmsis_dap_handle->packet_size = packet_size; - - if (cmsis_dap_handle->packet_buffer == NULL) { - LOG_ERROR("unable to allocate memory"); - return ERROR_FAIL; - } - return ERROR_OK; } -static void cmsis_dap_usb_close(struct cmsis_dap *dap) +static void cmsis_dap_close(struct cmsis_dap *dap) { - hid_close(dap->dev_handle); - hid_exit(); + if (dap->backend) { + dap->backend->close(dap); + dap->backend = NULL; + } free(cmsis_dap_handle->packet_buffer); free(cmsis_dap_handle); @@ -364,47 +306,27 @@ static void cmsis_dap_usb_close(struct cmsis_dap *dap) } } -static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen) -{ -#ifdef CMSIS_DAP_JTAG_DEBUG - LOG_DEBUG("cmsis-dap usb xfer cmd=%02X", dap->packet_buffer[1]); -#endif - /* Pad the rest of the TX buffer with 0's */ - memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen); - - /* write data to device */ - int retval = hid_write(dap->dev_handle, dap->packet_buffer, dap->packet_size); - if (retval == -1) { - LOG_ERROR("error writing data: %ls", hid_error(dap->dev_handle)); - return ERROR_FAIL; - } - - return ERROR_OK; -} - /* Send a message and receive the reply */ -static int cmsis_dap_usb_xfer(struct cmsis_dap *dap, int txlen) +static int cmsis_dap_xfer(struct cmsis_dap *dap, int txlen) { if (pending_fifo_block_count) { LOG_ERROR("pending %d blocks, flushing", pending_fifo_block_count); while (pending_fifo_block_count) { - hid_read_timeout(dap->dev_handle, dap->packet_buffer, dap->packet_size, 10); + dap->backend->read(dap, 10); pending_fifo_block_count--; } pending_fifo_put_idx = 0; pending_fifo_get_idx = 0; } - int retval = cmsis_dap_usb_write(dap, txlen); - if (retval != ERROR_OK) + int retval = dap->backend->write(dap, txlen, USB_TIMEOUT); + if (retval < 0) return retval; /* get reply */ - retval = hid_read_timeout(dap->dev_handle, dap->packet_buffer, dap->packet_size, USB_TIMEOUT); - if (retval == -1 || retval == 0) { - LOG_DEBUG("error reading data: %ls", hid_error(dap->dev_handle)); - return ERROR_FAIL; - } + retval = dap->backend->read(dap, USB_TIMEOUT); + if (retval < 0) + return retval; return ERROR_OK; } @@ -422,7 +344,7 @@ static int cmsis_dap_cmd_DAP_SWJ_Pins(uint8_t pins, uint8_t mask, uint32_t delay buffer[5] = (delay >> 8) & 0xff; buffer[6] = (delay >> 16) & 0xff; buffer[7] = (delay >> 24) & 0xff; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 8); + retval = cmsis_dap_xfer(cmsis_dap_handle, 8); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_PINS failed."); @@ -448,7 +370,7 @@ static int cmsis_dap_cmd_DAP_SWJ_Clock(uint32_t swj_clock) buffer[3] = (swj_clock >> 8) & 0xff; buffer[4] = (swj_clock >> 16) & 0xff; buffer[5] = (swj_clock >> 24) & 0xff; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 6); + retval = cmsis_dap_xfer(cmsis_dap_handle, 6); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_DAP_SWJ_CLOCK failed."); @@ -477,7 +399,7 @@ static int cmsis_dap_cmd_DAP_SWJ_Sequence(uint8_t s_len, const uint8_t *sequence buffer[2] = s_len; bit_copy(&buffer[3], 0, sequence, 0, s_len); - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); + retval = cmsis_dap_xfer(cmsis_dap_handle, DIV_ROUND_UP(s_len, 8) + 3); if (retval != ERROR_OK || buffer[1] != DAP_OK) return ERROR_FAIL; @@ -493,7 +415,7 @@ static int cmsis_dap_cmd_DAP_Info(uint8_t info, uint8_t **data) buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_INFO; buffer[2] = info; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); + retval = cmsis_dap_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_INFO failed."); @@ -514,7 +436,7 @@ static int cmsis_dap_cmd_DAP_LED(uint8_t led, uint8_t state) buffer[1] = CMD_DAP_LED; buffer[2] = led; buffer[3] = state; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4); + retval = cmsis_dap_xfer(cmsis_dap_handle, 4); if (retval != ERROR_OK || buffer[1] != 0x00) { LOG_ERROR("CMSIS-DAP command CMD_LED failed."); @@ -532,7 +454,7 @@ static int cmsis_dap_cmd_DAP_Connect(uint8_t mode) buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_CONNECT; buffer[2] = mode; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); + retval = cmsis_dap_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command CMD_CONNECT failed."); @@ -554,7 +476,7 @@ static int cmsis_dap_cmd_DAP_Disconnect(void) buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_DISCONNECT; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 2); + retval = cmsis_dap_xfer(cmsis_dap_handle, 2); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_DISCONNECT failed."); @@ -576,7 +498,7 @@ static int cmsis_dap_cmd_DAP_TFER_Configure(uint8_t idle, uint16_t retry_count, buffer[4] = (retry_count >> 8) & 0xff; buffer[5] = match_retry & 0xff; buffer[6] = (match_retry >> 8) & 0xff; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 7); + retval = cmsis_dap_xfer(cmsis_dap_handle, 7); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_TFER_Configure failed."); @@ -594,7 +516,7 @@ static int cmsis_dap_cmd_DAP_SWD_Configure(uint8_t cfg) buffer[0] = 0; /* report number */ buffer[1] = CMD_DAP_SWD_CONFIGURE; buffer[2] = cfg; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 3); + retval = cmsis_dap_xfer(cmsis_dap_handle, 3); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_SWD_Configure failed."); @@ -614,7 +536,7 @@ static int cmsis_dap_cmd_DAP_Delay(uint16_t delay_us) buffer[1] = CMD_DAP_DELAY; buffer[2] = delay_us & 0xff; buffer[3] = (delay_us >> 8) & 0xff; - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, 4); + retval = cmsis_dap_xfer(cmsis_dap_handle, 4); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_Delay failed."); @@ -684,9 +606,14 @@ static void cmsis_dap_swd_write_from_queue(struct cmsis_dap *dap) } } - queued_retval = cmsis_dap_usb_write(dap, idx); - if (queued_retval != ERROR_OK) + int retval = dap->backend->write(dap, idx, USB_TIMEOUT); + + if (retval < 0) { + queued_retval = retval; goto skip; + } else { + queued_retval = ERROR_OK; + } pending_fifo_put_idx = (pending_fifo_put_idx + 1) % dap->packet_count; pending_fifo_block_count++; @@ -708,12 +635,12 @@ static void cmsis_dap_swd_read_process(struct cmsis_dap *dap, int timeout_ms) LOG_ERROR("no pending write"); /* get reply */ - int retval = hid_read_timeout(dap->dev_handle, dap->packet_buffer, dap->packet_size, timeout_ms); - if (retval == 0 && timeout_ms < USB_TIMEOUT) + int retval = dap->backend->read(dap, timeout_ms); + if (retval == ERROR_TIMEOUT_REACHED && timeout_ms < USB_TIMEOUT) return; - if (retval == -1 || retval == 0) { - LOG_DEBUG("error reading data: %ls", hid_error(dap->dev_handle)); + if (retval <= 0) { + LOG_DEBUG("error reading data"); queued_retval = ERROR_FAIL; goto skip; } @@ -969,7 +896,7 @@ static int cmsis_dap_init(void) int retval; uint8_t *data; - retval = cmsis_dap_usb_open(); + retval = cmsis_dap_open(); if (retval != ERROR_OK) return retval; @@ -1048,7 +975,7 @@ static int cmsis_dap_init(void) LOG_DEBUG("CMSIS-DAP: Packet Count = %d", pkt_cnt); } - LOG_DEBUG("Allocating FIFO for %d pending HID requests", cmsis_dap_handle->packet_count); + LOG_DEBUG("Allocating FIFO for %d pending packets", cmsis_dap_handle->packet_count); for (int i = 0; i < cmsis_dap_handle->packet_count; i++) { pending_fifo[i].transfers = malloc(pending_queue_len * sizeof(struct pending_transfer_result)); if (!pending_fifo[i].transfers) { @@ -1120,7 +1047,7 @@ static int cmsis_dap_quit(void) cmsis_dap_cmd_DAP_LED(LED_ID_RUN, LED_OFF); cmsis_dap_cmd_DAP_LED(LED_ID_CONNECT, LED_OFF); - cmsis_dap_usb_close(cmsis_dap_handle); + cmsis_dap_close(cmsis_dap_handle); return ERROR_OK; } @@ -1261,7 +1188,7 @@ static void cmsis_dap_flush(void) #endif /* send command to USB device */ - int retval = cmsis_dap_usb_xfer(cmsis_dap_handle, queued_seq_buf_end + 3); + int retval = cmsis_dap_xfer(cmsis_dap_handle, queued_seq_buf_end + 3); if (retval != ERROR_OK || buffer[1] != DAP_OK) { LOG_ERROR("CMSIS-DAP command CMD_DAP_JTAG_SEQ failed."); exit(-1); @@ -1668,7 +1595,7 @@ COMMAND_HANDLER(cmsis_dap_handle_cmd_command) for (i = 0; i < CMD_ARGC; i++) buffer[i + 1] = strtoul(CMD_ARGV[i], NULL, 16); - retval = cmsis_dap_usb_xfer(cmsis_dap_handle, CMD_ARGC + 1); + retval = cmsis_dap_xfer(cmsis_dap_handle, CMD_ARGC + 1); if (retval != ERROR_OK) { LOG_ERROR("CMSIS-DAP command failed."); @@ -1712,21 +1639,32 @@ COMMAND_HANDLER(cmsis_dap_handle_vid_pid_command) } COMMAND_HANDLER(cmsis_dap_handle_serial_command) +{ + if (CMD_ARGC == 1) + cmsis_dap_serial = strdup(CMD_ARGV[0]); + else + LOG_ERROR("expected exactly one argument to cmsis_dap_serial <serial-number>"); + + return ERROR_OK; +} + +COMMAND_HANDLER(cmsis_dap_handle_backend_command) { if (CMD_ARGC == 1) { - size_t len = mbstowcs(NULL, CMD_ARGV[0], 0); - cmsis_dap_serial = calloc(len + 1, sizeof(wchar_t)); - if (cmsis_dap_serial == NULL) { - LOG_ERROR("unable to allocate memory"); - return ERROR_OK; - } - if (mbstowcs(cmsis_dap_serial, CMD_ARGV[0], len + 1) == (size_t)-1) { - free(cmsis_dap_serial); - cmsis_dap_serial = NULL; - LOG_ERROR("unable to convert serial"); + if (strcmp(CMD_ARGV[0], "auto") == 0) { + cmsis_dap_backend = -1; /* autoselect */ + } else { + for (unsigned int i = 0; i < ARRAY_SIZE(cmsis_dap_backends); i++) { + if (strcasecmp(cmsis_dap_backends[i]->name, CMD_ARGV[0]) == 0) { + cmsis_dap_backend = i; + return ERROR_OK; + } + } + + LOG_ERROR("invalid backend argument to cmsis_dap_backend <backend>"); } } else { - LOG_ERROR("expected exactly one argument to cmsis_dap_serial <serial-number>"); + LOG_ERROR("expected exactly one argument to cmsis_dap_backend <backend>"); } return ERROR_OK; @@ -1750,6 +1688,7 @@ static const struct command_registration cmsis_dap_subcommand_handlers[] = { COMMAND_REGISTRATION_DONE }; + static const struct command_registration cmsis_dap_command_handlers[] = { { .name = "cmsis-dap", @@ -1772,6 +1711,22 @@ static const struct command_registration cmsis_dap_command_handlers[] = { .help = "set the serial number of the adapter", .usage = "serial_string", }, + { + .name = "cmsis_dap_backend", + .handler = &cmsis_dap_handle_backend_command, + .mode = COMMAND_CONFIG, + .help = "set the communication backend to use (USB bulk or HID).", + .usage = "(auto | usb_bulk | hid)", + }, +#if BUILD_CMSIS_DAP_USB + { + .name = "cmsis_dap_usb", + .chain = cmsis_dap_usb_subcommand_handlers, + .mode = COMMAND_ANY, + .help = "USB bulk backend-specific commands", + .usage = "<cmd>", + }, +#endif COMMAND_REGISTRATION_DONE }; diff --git a/src/jtag/drivers/cmsis_dap.h b/src/jtag/drivers/cmsis_dap.h new file mode 100644 index 000000000..8cbb8dd07 --- /dev/null +++ b/src/jtag/drivers/cmsis_dap.h @@ -0,0 +1,28 @@ +#ifndef OPENOCD_JTAG_DRIVERS_CMSIS_DAP_H +#define OPENOCD_JTAG_DRIVERS_CMSIS_DAP_H + +#include <stdint.h> + +struct cmsis_dap_backend; +struct cmsis_dap_backend_data; +struct command_registration; + +struct cmsis_dap { + struct cmsis_dap_backend_data *bdata; + const struct cmsis_dap_backend *backend; + uint16_t packet_size; + int packet_count; + uint8_t *packet_buffer; + uint8_t caps; + uint8_t mode; +}; + +struct cmsis_dap_backend { + const char *name; + int (*open)(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial); + void (*close)(struct cmsis_dap *dap); + int (*read)(struct cmsis_dap *dap, int timeout_ms); + int (*write)(struct cmsis_dap *dap, int len, int timeout_ms); +}; + +#endif diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c new file mode 100644 index 000000000..b82e3dae5 --- /dev/null +++ b/src/jtag/drivers/cmsis_dap_usb_bulk.c @@ -0,0 +1,373 @@ +/*************************************************************************** + * Copyright (C) 2018 by Mickaël Thomas * + * mic...@gm... * + * * + * Copyright (C) 2016 by Maksym Hilliaka * + * ot...@fr... * + * * + * Copyright (C) 2016 by Phillip Pearson * + * pp...@my... * + * * + * Copyright (C) 2014 by Paul Fertser * + * fer...@gm... * + * * + * Copyright (C) 2013 by mike brown * + * mi...@th... * + * * + * Copyright (C) 2013 by Spencer Oliver * + * sp...@sp... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <libusb.h> +#include <helper/log.h> + +#include "cmsis_dap.h" + +struct cmsis_dap_backend_data { + libusb_context *usb_ctx; + libusb_device_handle *dev_handle; + unsigned int ep_out; + unsigned int ep_in; + int interface; +}; + +static int cmsis_dap_usb_interface = -1; + +static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial) +{ + int err; + libusb_context *ctx; + libusb_device **device_list; + + err = libusb_init(&ctx); + if (err) { + LOG_ERROR("libusb initialization failed: %s", libusb_strerror(err)); + return ERROR_FAIL; + } + + int num_devices = libusb_get_device_list(ctx, &device_list); + if (num_devices < 0) { + LOG_ERROR("could not enumerate USB devices: %s", libusb_strerror(num_devices)); + libusb_exit(ctx); + return ERROR_FAIL; + } + + for (int i = 0; i < num_devices; i++) { + libusb_device *dev = device_list[i]; + struct libusb_device_descriptor dev_desc; + + err = libusb_get_device_descriptor(dev, &dev_desc); + if (err) { + LOG_ERROR("could not get device descriptor for device %d: %s", i, libusb_strerror(err)); + continue; + } + + /* Match VID/PID */ + + bool id_match = true; /* match if we don't enter the loop (no filter) */ + for (int id = 0; vids[id] || pids[id]; id++) { + id_match = !vids[id] || dev_desc.idVendor == vids[id]; + id_match &= !pids[id] || dev_desc.idProduct == pids[id]; + + if (id_match) + break; + } + + if (!id_match) + continue; + + /* Don't continue if we asked for a serial number and the device doesn't have one */ + if (dev_desc.iSerialNumber == 0 && serial && serial[0]) + continue; + + libusb_device_handle *dev_handle = NULL; + err = libusb_open(dev, &dev_handle); + if (err) { + /* It's to be expected that most USB devices can't be opened + * so only report an error if it was explicitly selected + */ + if (vids[0] || pids[0]) { + LOG_ERROR("could not open device 0x%04x:0x%04x: %s", + dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + } else { + LOG_DEBUG("could not open device 0x%04x:0x%04x: %s", + dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + } + continue; + } + + /* Match serial number */ + + bool serial_match = (serial == NULL); + char dev_serial[256] = {0}; + if (dev_desc.iSerialNumber > 0) { + err = libusb_get_string_descriptor_ascii( + dev_handle, dev_desc.iSerialNumber, + (uint8_t *)dev_serial, sizeof(dev_serial)); + + if (err < 0) { + LOG_ERROR("could not read serial number for device 0x%04x:0x%04x: %s", + dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + } else if (serial && strncmp(dev_serial, serial, sizeof(dev_serial)) == 0) { + serial_match = true; + } + } + + if (!serial_match) { + libusb_close(dev_handle); + continue; + } + + /* Find the CMSIS-DAP string in product string */ + + bool cmsis_dap_found = false; + char product_string[256] = {0}; + if (dev_desc.iProduct > 0) { + err = libusb_get_string_descriptor_ascii( + dev_handle, dev_desc.iProduct, + (uint8_t *)product_string, sizeof(product_string)); + if (err < 0) { + LOG_ERROR("could not read product string for device 0x%04x:0x%04x: %s", + dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + } else if (strstr(product_string, "CMSIS-DAP")) { + LOG_DEBUG("CMSIS-DAP found in product string"); + cmsis_dap_found = true; + } + } + + /* Find the CMSIS-DAP interface */ + + for (int config = 0; config < dev_desc.bNumConfigurations; config++) { + struct libusb_config_descriptor *config_desc; + err = libusb_get_config_descriptor(dev, config, &config_desc); + if (err) { + LOG_ERROR("could not get configuration descriptor %d for device 0x%04x:0x%04x: %s", + config, dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + continue; + } + + int config_num = config_desc->bConfigurationValue; + + for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { + const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; + int interface_num = intf_desc->bInterfaceNumber; + + /* Skip this interface if another one was requested explicitly */ + if (cmsis_dap_usb_interface != -1 && cmsis_dap_usb_interface != interface_num) + continue; + + /* CMSIS-DAP v2 spec says: + * + * CMSIS-DAP with default V2 configuration uses WinUSB and is therefore faster. + * Optionally support for streaming SWO trace is provided via an additional USB endpoint. + * + * The WinUSB configuration requires custom class support with the interface setting + * Class Code: 0xFF (Vendor specific) + * Subclass: 0x00 + * Protocol code: 0x00 + * + * Depending on the configuration it uses the following USB endpoints which should be configured + * in the interface descriptor in this order: + * - Endpoint 1: Bulk Out â used for commands received from host PC. + * - Endpoint 2: Bulk In â used for responses send to host PC. + * - Endpoint 3: Bulk In (optional) â used for streaming SWO trace (if enabled with SWO_STREAM). + */ + + if (intf_desc->bNumEndpoints < 2) + continue; + + if ((intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || + (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT) + continue; + + if ((intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || + (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) + continue; + + /* Bypass the following checks if this interface was explicitly requested. */ + if (cmsis_dap_usb_interface == -1) { + if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC || + intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) + continue; + + /* Search for "CMSIS-DAP" in the interface string */ + if (cmsis_dap_usb_interface != -1 && !cmsis_dap_found) { + if (intf_desc->iInterface == 0) + continue; + + char interface_str[256] = {0}; + + err = libusb_get_string_descriptor_ascii( + dev_handle, intf_desc->iInterface, + (uint8_t *)interface_str, sizeof(interface_str)); + if (err < 0) { + LOG_ERROR("could not read interface string for device 0x%04x:0x%04x: %s", + dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); + continue; + } else if (!strstr(interface_str, "CMSIS-DAP")) { + continue; + } else { + LOG_DEBUG("CMSIS-DAP found in interface string"); + } + } + } + + int packet_size = intf_desc->endpoint[0].wMaxPacketSize; + int ep_out = intf_desc->endpoint[0].bEndpointAddress; + int ep_in = intf_desc->endpoint[1].bEndpointAddress; + + /* That's the one! */ + libusb_free_config_descriptor(config_desc); + libusb_free_device_list(device_list, true); + + LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s", + dev_desc.idVendor, dev_desc.idProduct, dev_serial); + + int current_config; + err = libusb_get_configuration(dev_handle, ¤t_config); + if (err) { + LOG_ERROR("could not find current configuration: %s", libusb_strerror(err)); + libusb_close(dev_handle); + libusb_exit(ctx); + return ERROR_FAIL; + } + + if (config_num != current_config) { + err = libusb_set_configuration(dev_handle, config_num); + if (err) { + LOG_ERROR("could not set configuration: %s", libusb_strerror(err)); + libusb_close(dev_handle); + libusb_exit(ctx); + return ERROR_FAIL; + } + } + + err = libusb_claim_interface(dev_handle, interface_num); + if (err) + LOG_WARNING("could not claim interface: %s", libusb_strerror(err)); + + dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); + if (dap->bdata == NULL) { + LOG_ERROR("unable to allocate memory"); + libusb_release_interface(dev_handle, interface_num); + libusb_close(dev_handle); + libusb_exit(ctx); + return ERROR_FAIL; + } + + dap->packet_size = packet_size + 1; /* "+ 1" for compatibility with the HID backend */ + dap->bdata->usb_ctx = ctx; + dap->bdata->dev_handle = dev_handle; + dap->bdata->ep_out = ep_out; + dap->bdata->ep_in = ep_in; + dap->bdata->interface = interface_num; + return ERROR_OK; + } + + libusb_free_config_descriptor(config_desc); + } + + libusb_close(dev_handle); + } + + libusb_free_device_list(device_list, true); + + libusb_exit(ctx); + return ERROR_FAIL; +} + +static void cmsis_dap_usb_close(struct cmsis_dap *dap) +{ + libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface); + libusb_close(dap->bdata->dev_handle); + libusb_exit(dap->bdata->usb_ctx); + free(dap->bdata); + dap->bdata = NULL; +} + +static int cmsis_dap_usb_read(struct cmsis_dap *dap, int timeout_ms) +{ + int transferred = 0; + int err; + + err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_in, + dap->packet_buffer, dap->packet_size, &transferred, timeout_ms); + if (err) { + if (err == LIBUSB_ERROR_TIMEOUT) { + return ERROR_TIMEOUT_REACHED; + } else { + LOG_ERROR("error reading data: %s", libusb_strerror(err)); + return ERROR_FAIL; + } + } + + memset(&dap->packet_buffer[transferred], 0, dap->packet_size - transferred); + + return transferred; +} + +static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) +{ + int transferred = 0; + int err; + + /* skip the first byte that is only used by the HID backend */ + err = libusb_bulk_transfer(dap->bdata->dev_handle, dap->bdata->ep_out, + dap->packet_buffer + 1, txlen - 1, &transferred, timeout_ms); + if (err) { + if (err == LIBUSB_ERROR_TIMEOUT) { + return ERROR_TIMEOUT_REACHED; + } else { + LOG_ERROR("error writing data: %s", libusb_strerror(err)); + return ERROR_FAIL; + } + } + + return transferred; +} + +COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command) +{ + if (CMD_ARGC == 1) + cmsis_dap_usb_interface = strtoul(CMD_ARGV[0], NULL, 10); + else + LOG_ERROR("expected exactly one argument to cmsis_dap_usb_interface <interface_number>"); + + return ERROR_OK; +} + +const struct command_registration cmsis_dap_usb_subcommand_handlers[] = { + { + .name = "interface", + .handler = &cmsis_dap_handle_usb_interface_command, + .mode = COMMAND_CONFIG, + .help = "set the USB interface number to use (for USB bulk backend only)", + .usage = "<interface_number>", + }, + COMMAND_REGISTRATION_DONE +}; + +const struct cmsis_dap_backend cmsis_dap_usb_backend = { + .name = "usb_bulk", + .open = cmsis_dap_usb_open, + .close = cmsis_dap_usb_close, + .read = cmsis_dap_usb_read, + .write = cmsis_dap_usb_write, +}; diff --git a/src/jtag/drivers/cmsis_dap_usb_hid.c b/src/jtag/drivers/cmsis_dap_usb_hid.c new file mode 100644 index 000000000..681aef171 --- /dev/null +++ b/src/jtag/drivers/cmsis_dap_usb_hid.c @@ -0,0 +1,208 @@ +/*************************************************************************** + * Copyright (C) 2018 by Mickaël Thomas * + * mic...@gm... * + * * + * Copyright (C) 2016 by Maksym Hilliaka * + * ot...@fr... * + * * + * Copyright (C) 2016 by Phillip Pearson * + * pp...@my... * + * * + * Copyright (C) 2014 by Paul Fertser * + * fer...@gm... * + * * + * Copyright (C) 2013 by mike brown * + * mi...@th... * + * * + * Copyright (C) 2013 by Spencer Oliver * + * sp...@sp... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <hidapi.h> +#include <helper/log.h> + +#include "cmsis_dap.h" + +#define PACKET_SIZE (64 + 1) /* 64 bytes plus report id */ + +struct cmsis_dap_backend_data { + hid_device *dev_handle; +}; + +static int cmsis_dap_hid_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], char *serial) +{ + hid_device *dev = NULL; + int i; + struct hid_device_info *devs, *cur_dev; + unsigned short target_vid, target_pid; + + target_vid = 0; + target_pid = 0; + + if (hid_init() != 0) { + LOG_ERROR("unable to open HIDAPI"); + return ERROR_FAIL; + } + + /* + * The CMSIS-DAP specification stipulates: + * "The Product String must contain "CMSIS-DAP" somewhere in the string. This is used by the + * debuggers to identify a CMSIS-DAP compliant Debug Unit that is connected to a host computer." + */ + devs = hid_enumerate(0x0, 0x0); + cur_dev = devs; + while (NULL != cur_dev) { + bool found = false; + + if (0 == vids[0]) { + if (NULL == cur_dev->product_string) { + LOG_DEBUG("Cannot read product string of device 0x%x:0x%x", + cur_dev->vendor_id, cur_dev->product_id); + } else if (wcsstr(cur_dev->product_string, L"CMSIS-DAP")) { + /* if the user hasn't specified VID:PID *and* + * product string contains "CMSIS-DAP", pick it + */ + found = true; + } + } else { + /* otherwise, exhaustively compare against all VID:PID in list */ + for (i = 0; vids[i] || pids[i]; i++) { + if ((vids[i] == cur_dev->vendor_id) && (pids[i] == cur_dev->product_id)) + found = true; + } + } + + /* LPC-LINK2 has cmsis-dap on interface 0 and other HID functions on other interfaces */ + if (cur_dev->vendor_id == 0x1fc9 && cur_dev->product_id == 0x0090 && cur_dev->interface_number != 0) + found = false; + + if (found) { + /* check serial number matches if given */ + if (serial == NULL) + break; + + if (cur_dev->serial_number != NULL) { + size_t len = (strlen(serial) + 1) * sizeof(wchar_t); + wchar_t *wserial = malloc(len); + mbstowcs(wserial, serial, len); + + if (wcscmp(wserial, cur_dev->serial_number) == 0) { + free(wserial); + break; + } else { + free(wserial); + wserial = NULL; + } + } + } + + cur_dev = cur_dev->next; + } + + if (NULL != cur_dev) { + target_vid = cur_dev->vendor_id; + target_pid = cur_dev->product_id; + } + + if (target_vid == 0 && target_pid == 0) { + hid_free_enumeration(devs); + return ERROR_FAIL; + } + + dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); + if (dap->bdata == NULL) { + LOG_ERROR("unable to allocate memory"); + return ERROR_FAIL; + } + + dev = hid_open_path(cur_dev->path); + hid_free_enumeration(devs); + + if (dev == NULL) { + LOG_ERROR("unable to open CMSIS-DAP device 0x%x:0x%x", target_vid, target_pid); + return ERROR_FAIL; + } + + /* allocate default packet buffer, may be changed later. + * currently with HIDAPI we have no way of getting the output report length + * without this info we cannot communicate with the adapter. + * For the moment we have to hard code the packet size */ + + dap->packet_size = PACKET_SIZE; + + /* atmel cmsis-dap uses 512 byte reports */ + /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained + * board */ + /* TODO: HID report descriptor should be parsed instead of + * hardcoding a match by VID */ + if (target_vid == 0x03eb && target_pid != 0x2145 && target_pid != 0x2175) + dap->packet_size = 512 + 1; + + dap->bdata->dev_handle = dev; + + return ERROR_OK; +} + +static void cmsis_dap_hid_close(struct cmsis_dap *dap) +{ + hid_close(dap->bdata->dev_handle); + hid_exit(); + free(dap->bdata); + dap->bdata = NULL; +} + +static int cmsis_dap_hid_read(struct cmsis_dap *dap, int timeout_ms) +{ + int retval = hid_read_timeout(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_size, timeout_ms); + + if (retval == 0) { + return ERROR_TIMEOUT_REACHED; + } else if (retval == -1) { + LOG_ERROR("error reading data: %ls", hid_error(dap->bdata->dev_handle)); + return ERROR_FAIL; + } + + return retval; +} + +static int cmsis_dap_hid_write(struct cmsis_dap *dap, int txlen, int timeout_ms) +{ + (void) timeout_ms; + + /* Pad the rest of the TX buffer with 0's */ + memset(dap->packet_buffer + txlen, 0, dap->packet_size - txlen); + + /* write data to device */ + int retval = hid_write(dap->bdata->dev_handle, dap->packet_buffer, dap->packet_size); + if (retval == -1) { + LOG_ERROR("error writing data: %ls", hid_error(dap->bdata->dev_handle)); + return ERROR_FAIL; + } + + return retval; +} + +const struct cmsis_dap_backend cmsis_dap_hid_backend = { + .name = "hid", + .open = cmsis_dap_hid_open, + .close = cmsis_dap_hid_close, + .read = cmsis_dap_hid_read, + .write = cmsis_dap_hid_write, +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 2fa53be2b..061a78f9c 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -134,7 +134,7 @@ extern struct adapter_driver aice_adapter_driver; #if BUILD_BCM2835GPIO == 1 extern struct adapter_driver bcm2835gpio_adapter_driver; #endif -#if BUILD_CMSIS_DAP == 1 +#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1 extern struct adapter_driver cmsis_dap_adapter_driver; #endif #if BUILD_KITPROG == 1 @@ -254,7 +254,7 @@ struct adapter_driver *adapter_drivers[] = { #if BUILD_BCM2835GPIO == 1 &bcm2835gpio_adapter_driver, #endif -#if BUILD_CMSIS_DAP == 1 +#if BUILD_CMSIS_DAP_USB == 1 || BUILD_CMSIS_DAP_HID == 1 &cmsis_dap_adapter_driver, #endif #if BUILD_KITPROG == 1 ----------------------------------------------------------------------- Summary of changes: configure.ac | 3 +- src/jtag/drivers/Makefile.am | 12 +- src/jtag/drivers/{cmsis_dap_usb.c => cmsis_dap.c} | 309 ++++++++---------- src/jtag/drivers/cmsis_dap.h | 28 ++ src/jtag/drivers/cmsis_dap_usb_bulk.c | 373 ++++++++++++++++++++++ src/jtag/drivers/cmsis_dap_usb_hid.c | 208 ++++++++++++ src/jtag/interfaces.c | 4 +- 7 files changed, 755 insertions(+), 182 deletions(-) rename src/jtag/drivers/{cmsis_dap_usb.c => cmsis_dap.c} (88%) create mode 100644 src/jtag/drivers/cmsis_dap.h create mode 100644 src/jtag/drivers/cmsis_dap_usb_bulk.c create mode 100644 src/jtag/drivers/cmsis_dap_usb_hid.c hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:10:24
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via b1f488ec1ea4c8b5410026610c621f85b5ff17f3 (commit) via 608299484d52a60082bb7ff5bcde5249f9a3a1de (commit) via f32ca2d25dae5526bf0bd70b1143aa34412fc7ec (commit) from fc91936be7bac7a84636d6b907ac545876263f3e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b1f488ec1ea4c8b5410026610c621f85b5ff17f3 Author: Tomas Vanek <va...@fb...> Date: Thu Oct 22 20:36:30 2020 +0200 target/armv7m, cortex_m: fix misleading comments Change-Id: I4fea29f07f4d3b8b2578b538ef0eef5f1eea285f Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5876 Tested-by: jenkins Reviewed-by: Christopher Head <ch...@za...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 13370b54b..f14ce0d88 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -493,8 +493,7 @@ int armv7m_start_algorithm(struct target *target, return ERROR_TARGET_NOT_HALTED; } - /* refresh core register cache - * Not needed if core register cache is always consistent with target process state */ + /* Store all non-debug execution registers to armv7m_algorithm_info context */ for (unsigned i = 0; i < armv7m->arm.core_cache->num_regs; i++) { armv7m_algorithm_info->context[i] = buf_get_u32( diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index fc72c0ed0..94cf82489 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -817,15 +817,19 @@ static int cortex_m_resume(struct target *target, int current, * in parallel with disabled interrupts can cause local faults * to not be taken. * - * REVISIT this clearly breaks non-debug execution, since the - * PRIMASK register state isn't saved/restored... workaround - * by never resuming app code after debug execution. + * This breaks non-debug (application) execution if not + * called from armv7m_start_algorithm() which saves registers. */ buf_set_u32(r->value, 0, 1, 1); r->dirty = true; r->valid = true; - /* Make sure we are in Thumb mode */ + /* Make sure we are in Thumb mode, set xPSR.T bit */ + /* armv7m_start_algorithm() initializes entire xPSR register. + * This duplicity handles the case when cortex_m_resume() + * is used with the debug_execution flag directly, + * not called through armv7m_start_algorithm(). + */ r = armv7m->arm.cpsr; buf_set_u32(r->value, 24, 1, 1); r->dirty = true; commit 608299484d52a60082bb7ff5bcde5249f9a3a1de Author: Tomas Vanek <va...@fb...> Date: Thu Oct 22 13:18:40 2020 +0200 flash/nor/psoc6: remove setting of xPSR.T bit from sromalgo_prepare() PSoC6 erases flash to 0x00 not more common 0xff, so a device with erased flash loads xPSR.T=0 from the zeroed reset vector. Wrong thumb bit value caused a target algorithm failed with HardFault. The low level write to xPSR solved the problem only if xPSR cached copy was not marked dirty. Later commit 49bd64347a21f5e12b33c256171b3035126d1260 fixed T setting for all Cortex-M target algorithms. Since 49bd64 this part of code is useless as xPSR target_start_algorithm() sets always xPSR dirty so the effect of the low level write is eliminated (and proper setting of thumb bit is ensured in target_start_algorithm()) Change-Id: I68aea5e921fbc6203f2fe91a45f10d22869327de Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5875 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 19d483bab..931404e3e 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -151,12 +151,6 @@ static int sromalgo_prepare(struct target *target) if (hr != ERROR_OK) return hr; - /* Restore THUMB bit in xPSR register */ - const struct armv7m_common *cm = target_to_armv7m(target); - hr = cm->store_core_reg_u32(target, ARMV7M_REGSEL_xPSR, 0x01000000); - if (hr != ERROR_OK) - return hr; - /* Allocate Working Area for Stack and Flash algorithm */ hr = target_alloc_working_area(target, RAM_STACK_WA_SIZE, &g_stack_area); if (hr != ERROR_OK) commit f32ca2d25dae5526bf0bd70b1143aa34412fc7ec Author: Tomas Vanek <va...@fb...> Date: Thu Oct 22 12:50:24 2020 +0200 target/cortex_m: remove wrong xPSR.ICI/IT bits handling If a Cortex-M (not M0, M0+) target was stopped in the middle of a conditional IT block or in the load/store multiple instruction, cortex_m_debug_entry() used wrong xPSR bits to detect it and then cleared 8 bits of the exception number from xPSR - probably wrong bit mask again. I believe clearing of the ICI/IT bits in cortex_m_debug_entry() has no reason as Cortex-M does not use instruction injecting. Remove the wrong code. The change was originally a part of http://openocd.zylin.com/4862 It is now re-submitted as #4862 is not ready. Change-Id: If91cd91d1b81b2684f7d5f10cf20452cde1a7f56 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5874 Tested-by: jenkins Reviewed-by: Christopher Head <ch...@za...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 7b3f3c70e..fc72c0ed0 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -527,12 +527,6 @@ static int cortex_m_debug_entry(struct target *target) r = arm->cpsr; xPSR = buf_get_u32(r->value, 0, 32); - /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */ - if (xPSR & 0xf00) { - r->dirty = r->valid; - cortex_m_store_core_reg_u32(target, ARMV7M_REGSEL_xPSR, xPSR & ~0xff); - } - /* Are we in an exception handler */ if (xPSR & 0x1FF) { armv7m->exception_number = (xPSR & 0x1FF); ----------------------------------------------------------------------- Summary of changes: src/flash/nor/psoc6.c | 6 ------ src/target/armv7m.c | 3 +-- src/target/cortex_m.c | 18 ++++++++---------- 3 files changed, 9 insertions(+), 18 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:09:20
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via fc91936be7bac7a84636d6b907ac545876263f3e (commit) via d811d2838b9edc230946a308917aedc28c9d111e (commit) from 4d336e8ffb7507f893640d344326b46f4bd8762d (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit fc91936be7bac7a84636d6b907ac545876263f3e Author: Tomas Vanek <va...@fb...> Date: Sun Oct 20 14:27:36 2019 +0200 target/armv7m: use arch_info[i].value instead of allocated memory Change-Id: I9422cab484d0769404516947e16da1baa001a4e0 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5328 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 7e9b72a8e..13370b54b 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -741,10 +741,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) reg_list[i].name = armv7m_regs[i].name; reg_list[i].size = armv7m_regs[i].bits; - size_t storage_size = DIV_ROUND_UP(armv7m_regs[i].bits, 8); - if (storage_size < 4) - storage_size = 4; - reg_list[i].value = calloc(1, storage_size); + reg_list[i].value = arch_info[i].value; reg_list[i].dirty = false; reg_list[i].valid = false; reg_list[i].hidden = i == ARMV7M_PMSK_BPRI_FLTMSK_CTRL; @@ -798,7 +795,6 @@ void armv7m_free_reg_cache(struct target *target) free(reg->feature); free(reg->reg_data_type); - free(reg->value); } free(cache->reg_list[0].arch_info); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index ced7a8a67..7b3f3c70e 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -2044,7 +2044,6 @@ int cortex_m_examine(struct target *target) for (idx = ARMV7M_NUM_CORE_REGS_NOFP; idx < armv7m->arm.core_cache->num_regs; idx++) { - free(armv7m->arm.core_cache->reg_list[idx].value); free(armv7m->arm.core_cache->reg_list[idx].feature); free(armv7m->arm.core_cache->reg_list[idx].reg_data_type); } commit d811d2838b9edc230946a308917aedc28c9d111e Author: Antonio Borneo <bor...@gm...> Date: Wed Oct 21 16:12:27 2020 +0200 cortex_m: use the new enum ARMV7M_REGSEL_name Register xPSR is indexed directly with its value 16 or with the incorrect enum ARMV7M_xPSR. Replace them with the new enum ARMV7M_REGSEL_xPSR. Change-Id: I86600e7f78e39002ce45f66d4792d5067c1f541b Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5873 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 30bf88501..19d483bab 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -153,7 +153,7 @@ static int sromalgo_prepare(struct target *target) /* Restore THUMB bit in xPSR register */ const struct armv7m_common *cm = target_to_armv7m(target); - hr = cm->store_core_reg_u32(target, ARMV7M_xPSR, 0x01000000); + hr = cm->store_core_reg_u32(target, ARMV7M_REGSEL_xPSR, 0x01000000); if (hr != ERROR_OK) return hr; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 72a2bd322..ced7a8a67 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -530,7 +530,7 @@ static int cortex_m_debug_entry(struct target *target) /* For IT instructions xPSR must be reloaded on resume and clear on debug exec */ if (xPSR & 0xf00) { r->dirty = r->valid; - cortex_m_store_core_reg_u32(target, 16, xPSR & ~0xff); + cortex_m_store_core_reg_u32(target, ARMV7M_REGSEL_xPSR, xPSR & ~0xff); } /* Are we in an exception handler */ ----------------------------------------------------------------------- Summary of changes: src/flash/nor/psoc6.c | 2 +- src/target/armv7m.c | 6 +----- src/target/cortex_m.c | 3 +-- 3 files changed, 3 insertions(+), 8 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:08:35
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 4d336e8ffb7507f893640d344326b46f4bd8762d (commit) via be631eed16bd9ef2b735fd64650ca7283d2ca361 (commit) from 62394a6b1c25ac92630a4828ec1b5d70acfe6e0f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 4d336e8ffb7507f893640d344326b46f4bd8762d Author: Antonio Borneo <bor...@gm...> Date: Sun Oct 25 17:35:45 2020 +0100 stlink: handle read/write FPU registers in HLA API Old stlink firmware in stlink V1 and stlink V2 pre-J15 do not handle FPU registers in the read_reg() and write_reg() API. Add code to be compatible with the new API of OpenOCD. Change-Id: Ib0439c5294b6911ea75efe8c7fa085b014317a4b Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5883 Tested-by: jenkins Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 1d38103a2..4545bcba0 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -324,6 +324,9 @@ struct stlink_usb_handle_s { /* aliases */ #define STLINK_F_HAS_TARGET_VOLT STLINK_F_HAS_TRACE +#define STLINK_F_HAS_FPU_REG STLINK_F_HAS_GETLASTRWSTATUS2 + +#define STLINK_REGSEL_IS_FPU(x) ((x) > 0x1F) struct speed_map { int speed; @@ -2023,6 +2026,15 @@ static int stlink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) assert(handle != NULL); + if (STLINK_REGSEL_IS_FPU(regsel) && !(h->version.flags & STLINK_F_HAS_FPU_REG)) { + res = stlink_usb_write_debug_reg(h, DCB_DCRSR, regsel & 0x7f); + if (res != ERROR_OK) + return res; + + /* FIXME: poll DHCSR.S_REGRDY before read DCRDR */ + return stlink_usb_v2_read_debug_reg(h, DCB_DCRDR, val); + } + stlink_usb_init_buffer(handle, h->rx_ep, h->version.jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; @@ -2054,6 +2066,15 @@ static int stlink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) assert(handle != NULL); + if (STLINK_REGSEL_IS_FPU(regsel) && !(h->version.flags & STLINK_F_HAS_FPU_REG)) { + int res = stlink_usb_write_debug_reg(h, DCB_DCRDR, val); + if (res != ERROR_OK) + return res; + + return stlink_usb_write_debug_reg(h, DCB_DCRSR, DCRSR_WnR | (regsel & 0x7f)); + /* FIXME: poll DHCSR.S_REGRDY after write DCRSR */ + } + stlink_usb_init_buffer(handle, h->rx_ep, 2); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; commit be631eed16bd9ef2b735fd64650ca7283d2ca361 Author: Antonio Borneo <bor...@gm...> Date: Sun Oct 25 14:59:13 2020 +0100 hla: API: specify that read_reg/write_reg use regsel as parameter The API of hla have been defined from ST-Link basic operations. By chance, all the current implementation of hla (st-link, ti-icdi and nulink) share the same way to handle the parameter 'num' of the API read_reg() and write_reg(), that is simply using it to initialize the field REGSEL (bits [6:0]) of armv7m Debug Core Register Selector Register (DCRSR). Add a comment in the API definition to highlight this, in case it get used by a further hla implementation, then rename as 'regsel' the 'num' parameter. Change-Id: I4b6a2c7d78b4fc4de2b9b2bdba065414b15c6ba3 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5882 Reviewed-by: Edward Fewell <edw...@ho...> Tested-by: jenkins Reviewed-by: Zale Yu Reviewed-by: Tomas Vanek <va...@fb...> diff --git a/src/jtag/drivers/nulink_usb.c b/src/jtag/drivers/nulink_usb.c index 5fdbed3fc..00738ee4e 100644 --- a/src/jtag/drivers/nulink_usb.c +++ b/src/jtag/drivers/nulink_usb.c @@ -411,7 +411,7 @@ static int nulink_usb_step(void *handle) return res; } -static int nulink_usb_read_reg(void *handle, int num, uint32_t *val) +static int nulink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { struct nulink_usb_handle_s *h = handle; @@ -434,7 +434,7 @@ static int nulink_usb_read_reg(void *handle, int num, uint32_t *val) h->cmdbuf[h->cmdidx] = 0; h->cmdidx += 1; /* u32Addr */ - h_u32_to_le(h->cmdbuf + h->cmdidx, num); + h_u32_to_le(h->cmdbuf + h->cmdidx, regsel); h->cmdidx += 4; /* u32Data */ h_u32_to_le(h->cmdbuf + h->cmdidx, 0); @@ -450,7 +450,7 @@ static int nulink_usb_read_reg(void *handle, int num, uint32_t *val) return res; } -static int nulink_usb_write_reg(void *handle, int num, uint32_t val) +static int nulink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) { struct nulink_usb_handle_s *h = handle; @@ -473,7 +473,7 @@ static int nulink_usb_write_reg(void *handle, int num, uint32_t val) h->cmdbuf[h->cmdidx] = 0; h->cmdidx += 1; /* u32Addr */ - h_u32_to_le(h->cmdbuf + h->cmdidx, num); + h_u32_to_le(h->cmdbuf + h->cmdidx, regsel); h->cmdidx += 4; /* u32Data */ h_u32_to_le(h->cmdbuf + h->cmdidx, val); diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index c54e2cc19..1d38103a2 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2016,7 +2016,7 @@ static int stlink_usb_read_regs(void *handle) } /** */ -static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) +static int stlink_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { int res; struct stlink_usb_handle_s *h = handle; @@ -2030,7 +2030,7 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_READREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READREG; - h->cmdbuf[h->cmdidx++] = num; + h->cmdbuf[h->cmdidx++] = regsel; if (h->version.jtag_api == STLINK_JTAG_API_V1) { res = stlink_usb_xfer_noerrcheck(handle, h->databuf, 4); @@ -2048,7 +2048,7 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) } /** */ -static int stlink_usb_write_reg(void *handle, int num, uint32_t val) +static int stlink_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) { struct stlink_usb_handle_s *h = handle; @@ -2061,7 +2061,7 @@ static int stlink_usb_write_reg(void *handle, int num, uint32_t val) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEREG; else h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEREG; - h->cmdbuf[h->cmdidx++] = num; + h->cmdbuf[h->cmdidx++] = regsel; h_u32_to_le(h->cmdbuf+h->cmdidx, val); h->cmdidx += 4; diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index 920be7783..00b2f9675 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -475,13 +475,13 @@ static int icdi_usb_read_regs(void *handle) return ERROR_OK; } -static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) +static int icdi_usb_read_reg(void *handle, unsigned int regsel, uint32_t *val) { int result; struct icdi_usb_handle_s *h = handle; char cmd[10]; - snprintf(cmd, sizeof(cmd), "p%x", num); + snprintf(cmd, sizeof(cmd), "p%x", regsel); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) return result; @@ -504,14 +504,14 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) return result; } -static int icdi_usb_write_reg(void *handle, int num, uint32_t val) +static int icdi_usb_write_reg(void *handle, unsigned int regsel, uint32_t val) { int result; char cmd[20]; uint8_t buf[4]; h_u32_to_le(buf, val); - int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); + int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", regsel); hexify(cmd + cmd_len, buf, 4, sizeof(cmd)); result = icdi_send_cmd(handle, cmd); diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h index e0bbd0fed..a8088fe95 100644 --- a/src/jtag/hla/hla_layout.h +++ b/src/jtag/hla/hla_layout.h @@ -51,10 +51,25 @@ struct hl_layout_api_s { int (*step)(void *handle); /** */ int (*read_regs)(void *handle); - /** */ - int (*read_reg)(void *handle, int num, uint32_t *val); - /** */ - int (*write_reg)(void *handle, int num, uint32_t val); + /** + * Read one register from the target + * + * @param handle A pointer to the device-specific handle + * @param regsel Register selection index compatible with all the + * values allowed by armv7m DCRSR.REGSEL + * @param val A pointer to retrieve the register value + * @returns ERROR_OK on success, or an error code on failure. + */ + int (*read_reg)(void *handle, unsigned int regsel, uint32_t *val); + /** + * Write one register to the target + * @param handle A pointer to the device-specific handle + * @param regsel Register selection index compatible with all the + * values allowed by armv7m DCRSR.REGSEL + * @param val The value to be written in the register + * @returns ERROR_OK on success, or an error code on failure. + */ + int (*write_reg)(void *handle, unsigned int regsel, uint32_t val); /** */ int (*read_mem)(void *handle, uint32_t addr, uint32_t size, uint32_t count, uint8_t *buffer); ----------------------------------------------------------------------- Summary of changes: src/jtag/drivers/nulink_usb.c | 8 ++++---- src/jtag/drivers/stlink_usb.c | 29 +++++++++++++++++++++++++---- src/jtag/drivers/ti_icdi_usb.c | 8 ++++---- src/jtag/hla/hla_layout.h | 23 +++++++++++++++++++---- 4 files changed, 52 insertions(+), 16 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:07:58
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 62394a6b1c25ac92630a4828ec1b5d70acfe6e0f (commit) from d3a37b0e76ece5625db74b4f343ebcc90059657f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 62394a6b1c25ac92630a4828ec1b5d70acfe6e0f Author: Tomas Vanek <va...@fb...> Date: Wed Oct 14 21:03:02 2020 +0200 target/cortex_m,hla_target: rework Cortex-M register handling part 4 Consolidate low level register read/write. Floating point registers were handled by target_read/write_u32 unlike other registers handled by cortexm_dap_read/write_coreregister_u32 There is no reason to do so in cortex_m. Remove cortexm_dap_read/write_coreregister_u32 and use cortex_m_load/store_core_reg_u32 directly. Similarly HLA adapters register read/write interface supports all registers so use it for any floating point and other registers. Change-Id: Ida679e5f4fec02d94ffb0bd3f265ed7ed2221cdc Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5864 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 00e7c3a57..72a2bd322 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -56,8 +56,8 @@ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t num, uint32_t value); static void cortex_m_dwt_free(struct target *target); -static int cortexm_dap_read_coreregister_u32(struct target *target, - uint32_t *value, int regnum) +static int cortex_m_load_core_reg_u32(struct target *target, + uint32_t regsel, uint32_t *value) { struct armv7m_common *armv7m = target_to_armv7m(target); int retval; @@ -71,7 +71,7 @@ static int cortexm_dap_read_coreregister_u32(struct target *target, return retval; } - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regnum); + retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DCRSR, regsel); if (retval != ERROR_OK) return retval; @@ -89,8 +89,8 @@ static int cortexm_dap_read_coreregister_u32(struct target *target, return retval; } -static int cortexm_dap_write_coreregister_u32(struct target *target, - uint32_t value, int regnum) +static int cortex_m_store_core_reg_u32(struct target *target, + uint32_t regsel, uint32_t value) { struct armv7m_common *armv7m = target_to_armv7m(target); int retval; @@ -108,7 +108,7 @@ static int cortexm_dap_write_coreregister_u32(struct target *target, if (retval != ERROR_OK) return retval; - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regnum | DCRSR_WnR); + retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DCRSR, regsel | DCRSR_WnR); if (retval != ERROR_OK) return retval; @@ -1606,117 +1606,6 @@ void cortex_m_enable_watchpoints(struct target *target) } } -static int cortex_m_load_core_reg_u32(struct target *target, - uint32_t regsel, uint32_t *value) -{ - int retval; - - switch (regsel) { - case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: - /* read a normal core register */ - retval = cortexm_dap_read_coreregister_u32(target, value, regsel); - - if (retval != ERROR_OK) { - LOG_ERROR("JTAG failure %i", retval); - return ERROR_JTAG_DEVICE_ERROR; - } - LOG_DEBUG("load from core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); - break; - - case ARMV7M_REGSEL_FPSCR: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRSR, ARMV7M_REGSEL_FPSCR); - if (retval != ERROR_OK) - return retval; - retval = target_read_u32(target, DCB_DCRDR, value); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); - break; - - case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRSR, regsel); - if (retval != ERROR_OK) - return retval; - retval = target_read_u32(target, DCB_DCRDR, value); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, - (int)(regsel - ARMV7M_REGSEL_S0), *value); - break; - - case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: - retval = cortexm_dap_read_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("load from special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, *value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - -static int cortex_m_store_core_reg_u32(struct target *target, - uint32_t regsel, uint32_t value) -{ - int retval; - struct armv7m_common *armv7m = target_to_armv7m(target); - - switch (regsel) { - case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: - retval = cortexm_dap_write_coreregister_u32(target, value, regsel); - if (retval != ERROR_OK) { - struct reg *r; - - LOG_ERROR("JTAG failure"); - r = armv7m->arm.core_cache->reg_list + regsel; /* TODO: don't use regsel as register index */ - r->dirty = r->valid; - return ERROR_JTAG_DEVICE_ERROR; - } - LOG_DEBUG("write core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, value); - break; - - case ARMV7M_REGSEL_FPSCR: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRDR, value); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, DCB_DCRSR, ARMV7M_REGSEL_FPSCR | DCRSR_WnR); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); - break; - - case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRDR, value); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, DCB_DCRSR, regsel | DCRSR_WnR); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, - (int)(regsel - ARMV7M_REGSEL_S0), value); - break; - - case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: - cortexm_dap_write_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - - LOG_DEBUG("write special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; -} - static int cortex_m_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { diff --git a/src/target/hla_target.c b/src/target/hla_target.c index 725c2d2fe..99afccc49 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -53,123 +53,15 @@ static inline struct hl_interface_s *target_to_adapter(struct target *target) static int adapter_load_core_reg_u32(struct target *target, uint32_t regsel, uint32_t *value) { - int retval; struct hl_interface_s *adapter = target_to_adapter(target); - - LOG_DEBUG("%s", __func__); - - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (regsel) { - case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: - /* read a normal core register */ - retval = adapter->layout->api->read_reg(adapter->handle, regsel, value); - - if (retval != ERROR_OK) { - LOG_ERROR("JTAG failure %i", retval); - return ERROR_JTAG_DEVICE_ERROR; - } - LOG_DEBUG("load from core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); - break; - - case ARMV7M_REGSEL_FPSCR: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel); - if (retval != ERROR_OK) - return retval; - retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); - break; - - case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel); - if (retval != ERROR_OK) - return retval; - retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, - (int)(regsel - ARMV7M_REGSEL_S0), *value); - break; - - case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: - retval = adapter->layout->api->read_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, value); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("load from special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, *value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; + return adapter->layout->api->read_reg(adapter->handle, regsel, value); } static int adapter_store_core_reg_u32(struct target *target, uint32_t regsel, uint32_t value) { - int retval; - struct armv7m_common *armv7m = target_to_armv7m(target); struct hl_interface_s *adapter = target_to_adapter(target); - - LOG_DEBUG("%s", __func__); - - switch (regsel) { - case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: - retval = adapter->layout->api->write_reg(adapter->handle, regsel, value); - - if (retval != ERROR_OK) { - struct reg *r; - - LOG_ERROR("JTAG failure"); - r = armv7m->arm.core_cache->reg_list + regsel; /* TODO: don't use regsel as register index */ - r->dirty = r->valid; - return ERROR_JTAG_DEVICE_ERROR; - } - LOG_DEBUG("write core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, value); - break; - - case ARMV7M_REGSEL_FPSCR: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, ARMV7M_REGSEL_FPSCR | DCRSR_WnR); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); - break; - - case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: - /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel | DCRSR_WnR); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, - (int)(regsel - ARMV7M_REGSEL_S0), value); - break; - - case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: - adapter->layout->api->write_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, value); - - LOG_DEBUG("write special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, value); - break; - - default: - return ERROR_COMMAND_SYNTAX_ERROR; - } - - return ERROR_OK; + return adapter->layout->api->write_reg(adapter->handle, regsel, value); } static int adapter_examine_debug_reason(struct target *target) ----------------------------------------------------------------------- Summary of changes: src/target/cortex_m.c | 123 +++--------------------------------------------- src/target/hla_target.c | 112 +------------------------------------------ 2 files changed, 8 insertions(+), 227 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:07:03
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via d3a37b0e76ece5625db74b4f343ebcc90059657f (commit) via e4160bd42216d5e717822162e1dad83b1b7003a1 (commit) from efbc447ed8d49ef0fa0638faf13315d767208ab6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d3a37b0e76ece5625db74b4f343ebcc90059657f Author: Tomas Vanek <va...@fb...> Date: Wed Oct 14 20:23:50 2020 +0200 target/armv7m: rework Cortex-M register handling part 3 Move primask/basepri/faultmask/control packing/unpacking from cortex_m.c and hla_target.c to armv7m.c armv7m_read_core_reg() and armv7m_write_core_reg() where also the FP 32/64-bit registers conversion takes place. Introduce a new hidden register ARMV7M_PMSK_BPRI_FLTMSK_CTRL for packing/unpacking of special registers in the register cache. The new packing/unpacking is endianess safe. While on it improve returned error codes and LOG_ messages. Just minimal changes in cortex_m.c and hla_target.c, will be consolidated in the next patch. Change-Id: Id51e764e243e54b5fdaadf2a202eee7c4bc729fe Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5863 Tested-by: jenkins Reviewed-by: Christopher Head <ch...@za...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 177437391..7e9b72a8e 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -14,6 +14,9 @@ * Copyright (C) 2018 by Liviu Ionescu * * <il...@li...> * * * + * Copyright (C) 2019 by Tomas Vanek * + * va...@fb... * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -108,6 +111,15 @@ static const struct { { ARMV7M_MSP, "msp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_PSP, "psp", 32, REG_TYPE_DATA_PTR, "system", "org.gnu.gdb.arm.m-system" }, + /* A working register for packing/unpacking special regs, hidden from gdb */ + { ARMV7M_PMSK_BPRI_FLTMSK_CTRL, "pmsk_bpri_fltmsk_ctrl", 32, REG_TYPE_INT, NULL, NULL }, + + /* WARNING: If you use armv7m_write_core_reg() on one of 4 following + * special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL + * cache only and are not flushed to CPU HW register. + * To trigger write to CPU HW register, add + * armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,); + */ { ARMV7M_PRIMASK, "primask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_BASEPRI, "basepri", 8, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, { ARMV7M_FAULTMASK, "faultmask", 1, REG_TYPE_INT8, "system", "org.gnu.gdb.arm.m-system" }, @@ -150,6 +162,9 @@ int armv7m_restore_context(struct target *target) if (armv7m->pre_restore_context) armv7m->pre_restore_context(target); + /* The descending order of register writes is crucial for correct + * packing of ARMV7M_PMSK_BPRI_FLTMSK_CTRL! + * See also comments in the register table above */ for (i = cache->num_regs - 1; i >= 0; i--) { if (cache->reg_list[i].dirty) { armv7m->arm.write_core_reg(target, &cache->reg_list[i], i, @@ -225,23 +240,45 @@ static uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) */ return arm_reg_id; + case ARMV7M_PMSK_BPRI_FLTMSK_CTRL: + return ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL; + case ARMV7M_FPSCR: return ARMV7M_REGSEL_FPSCR; case ARMV7M_D0 ... ARMV7M_D15: return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0); - /* TODO: remove. This is temporary hack until packing/unpacking - * of special regs is moved to armv7m.c */ + default: + LOG_ERROR("Bad register ID %u", arm_reg_id); + return arm_reg_id; + } +} + +static bool armv7m_map_reg_packing(unsigned int arm_reg_id, + unsigned int *reg32_id, uint32_t *offset) +{ + switch (arm_reg_id) { + case ARMV7M_PRIMASK: + *reg32_id = ARMV7M_PMSK_BPRI_FLTMSK_CTRL; + *offset = 0; + return true; case ARMV7M_BASEPRI: + *reg32_id = ARMV7M_PMSK_BPRI_FLTMSK_CTRL; + *offset = 1; + return true; case ARMV7M_FAULTMASK: + *reg32_id = ARMV7M_PMSK_BPRI_FLTMSK_CTRL; + *offset = 2; + return true; case ARMV7M_CONTROL: - return arm_reg_id; + *reg32_id = ARMV7M_PMSK_BPRI_FLTMSK_CTRL; + *offset = 3; + return true; default: - LOG_ERROR("Bad register ID %u", arm_reg_id); - return arm_reg_id; + return false; } } @@ -250,85 +287,134 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, { uint32_t reg_value; int retval; - struct arm_reg *armv7m_core_reg; struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); assert(num == (int)r->number); - armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; + /* If a code calls read_reg, it expects the cache is no more dirty. + * Clear the dirty flag regardless of the later read succeeds or not + * to prevent unwanted cache flush after a read error */ + r->dirty = false; - uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); + if (r->size <= 8) { + /* any 8-bit or shorter register is packed */ + uint32_t offset = 0; /* silence false gcc warning */ + unsigned int reg32_id; + + bool is_packed = armv7m_map_reg_packing(num, ®32_id, &offset); + assert(is_packed); + struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id]; + + /* Read 32-bit container register if not cached */ + if (!r32->valid) { + retval = armv7m_read_core_reg(target, r32, reg32_id, mode); + if (retval != ERROR_OK) + return retval; + } + + /* Copy required bits of 32-bit container register */ + buf_cpy(r32->value + offset, r->value, r->size); - if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { - /* map D0..D15 to S0..S31 */ - retval = armv7m->load_core_reg_u32(target, regsel, ®_value); - if (retval != ERROR_OK) - return retval; - buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, - 0, 32, reg_value); - retval = armv7m->load_core_reg_u32(target, regsel + 1, ®_value); - if (retval != ERROR_OK) - return retval; - buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4, - 0, 32, reg_value); } else { - retval = armv7m->load_core_reg_u32(target, - regsel, ®_value); + assert(r->size == 32 || r->size == 64); + + struct arm_reg *armv7m_core_reg = r->arch_info; + uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); + + retval = armv7m->load_core_reg_u32(target, regsel, ®_value); if (retval != ERROR_OK) return retval; - buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); + buf_set_u32(r->value, 0, 32, reg_value); + + if (r->size == 64) { + retval = armv7m->load_core_reg_u32(target, regsel + 1, ®_value); + if (retval != ERROR_OK) { + r->valid = false; + return retval; + } + buf_set_u32(r->value + 4, 0, 32, reg_value); + + uint64_t q = buf_get_u64(r->value, 0, 64); + LOG_DEBUG("read %s value 0x%016" PRIx64, r->name, q); + } else { + LOG_DEBUG("read %s value 0x%08" PRIx32, r->name, reg_value); + } } - armv7m->arm.core_cache->reg_list[num].valid = true; - armv7m->arm.core_cache->reg_list[num].dirty = false; + r->valid = true; - return retval; + return ERROR_OK; } static int armv7m_write_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode, uint8_t *value) { int retval; - struct arm_reg *armv7m_core_reg; + uint32_t t; struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); assert(num == (int)r->number); - armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; + if (value != r->value) { + /* If we are not flushing the cache, store the new value to the cache */ + buf_cpy(value, r->value, r->size); + } - uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); + if (r->size <= 8) { + /* any 8-bit or shorter register is packed */ + uint32_t offset = 0; /* silence false gcc warning */ + unsigned int reg32_id; - if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { - /* map D0..D15 to S0..S31 */ - uint32_t t = buf_get_u32(value, 0, 32); - retval = armv7m->store_core_reg_u32(target, regsel, t); - if (retval != ERROR_OK) - goto out_error; + bool is_packed = armv7m_map_reg_packing(num, ®32_id, &offset); + assert(is_packed); + struct reg *r32 = &armv7m->arm.core_cache->reg_list[reg32_id]; + + if (!r32->valid) { + /* Before merging with other parts ensure the 32-bit register is valid */ + retval = armv7m_read_core_reg(target, r32, reg32_id, mode); + if (retval != ERROR_OK) + return retval; + } + + /* Write a part to the 32-bit container register */ + buf_cpy(value, r32->value + offset, r->size); + r32->dirty = true; - t = buf_get_u32(value + 4, 0, 32); - retval = armv7m->store_core_reg_u32(target, regsel + 1, t); - if (retval != ERROR_OK) - goto out_error; } else { - uint32_t t = buf_get_u32(value, 0, 32); + assert(r->size == 32 || r->size == 64); + + struct arm_reg *armv7m_core_reg = r->arch_info; + uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); - LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t); + t = buf_get_u32(value, 0, 32); retval = armv7m->store_core_reg_u32(target, regsel, t); if (retval != ERROR_OK) goto out_error; + + if (r->size == 64) { + t = buf_get_u32(value + 4, 0, 32); + retval = armv7m->store_core_reg_u32(target, regsel + 1, t); + if (retval != ERROR_OK) + goto out_error; + + uint64_t q = buf_get_u64(value, 0, 64); + LOG_DEBUG("write %s value 0x%016" PRIx64, r->name, q); + } else { + LOG_DEBUG("write %s value 0x%08" PRIx32, r->name, t); + } } - armv7m->arm.core_cache->reg_list[num].valid = true; - armv7m->arm.core_cache->reg_list[num].dirty = false; + r->valid = true; + r->dirty = false; return ERROR_OK; out_error: - LOG_ERROR("Error setting register"); - armv7m->arm.core_cache->reg_list[num].dirty = armv7m->arm.core_cache->reg_list[num].valid; - return ERROR_JTAG_DEVICE_ERROR; + r->dirty = true; + LOG_ERROR("Error setting register %s", r->name); + return retval; } /** @@ -661,6 +747,7 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) reg_list[i].value = calloc(1, storage_size); reg_list[i].dirty = false; reg_list[i].valid = false; + reg_list[i].hidden = i == ARMV7M_PMSK_BPRI_FLTMSK_CTRL; reg_list[i].type = &armv7m_reg_type; reg_list[i].arch_info = &arch_info[i]; @@ -669,6 +756,9 @@ struct reg_cache *armv7m_build_reg_cache(struct target *target) reg_list[i].exist = true; reg_list[i].caller_save = true; /* gdb defaults to true */ + if (reg_list[i].hidden) + continue; + feature = calloc(1, sizeof(struct reg_feature)); if (feature) { feature->name = armv7m_regs[i].feature; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index bd10905b8..db6f8bc52 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -128,6 +128,16 @@ enum { ARMV7M_PSP = ARMV7M_REGSEL_PSP, /* following indices are arbitrary, do not match DCRSR.REGSEL selectors */ + + /* working register for packing/unpacking special regs, hidden from gdb */ + ARMV7M_PMSK_BPRI_FLTMSK_CTRL, + + /* WARNING: If you use armv7m_write_core_reg() on one of 4 following + * special registers, the new data go to ARMV7M_PMSK_BPRI_FLTMSK_CTRL + * cache only and are not flushed to CPU HW register. + * To trigger write to CPU HW register, add + * armv7m_write_core_reg(,,ARMV7M_PMSK_BPRI_FLTMSK_CTRL,); + */ ARMV7M_PRIMASK, ARMV7M_BASEPRI, ARMV7M_FAULTMASK, diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4df903e66..00e7c3a57 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1646,35 +1646,12 @@ static int cortex_m_load_core_reg_u32(struct target *target, (int)(regsel - ARMV7M_REGSEL_S0), *value); break; - case ARMV7M_PRIMASK: - case ARMV7M_BASEPRI: - case ARMV7M_FAULTMASK: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * in one Debug Core register. So say r0 and r2 docs; - * it was removed from r1 docs, but still works. - */ - cortexm_dap_read_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - - switch (regsel) { - case ARMV7M_PRIMASK: - *value = buf_get_u32((uint8_t *)value, 0, 1); - break; - - case ARMV7M_BASEPRI: - *value = buf_get_u32((uint8_t *)value, 8, 8); - break; - - case ARMV7M_FAULTMASK: - *value = buf_get_u32((uint8_t *)value, 16, 1); - break; - - case ARMV7M_CONTROL: - *value = buf_get_u32((uint8_t *)value, 24, 3); - break; - } + case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: + retval = cortexm_dap_read_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); + if (retval != ERROR_OK) + return retval; - LOG_DEBUG("load from special reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); + LOG_DEBUG("load from special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, *value); break; default: @@ -1688,7 +1665,6 @@ static int cortex_m_store_core_reg_u32(struct target *target, uint32_t regsel, uint32_t value) { int retval; - uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); switch (regsel) { @@ -1728,37 +1704,10 @@ static int cortex_m_store_core_reg_u32(struct target *target, (int)(regsel - ARMV7M_REGSEL_S0), value); break; - case ARMV7M_PRIMASK: - case ARMV7M_BASEPRI: - case ARMV7M_FAULTMASK: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * in one Debug Core register. So say r0 and r2 docs; - * it was removed from r1 docs, but still works. - */ - cortexm_dap_read_coreregister_u32(target, ®, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - - switch (regsel) { - case ARMV7M_PRIMASK: - buf_set_u32((uint8_t *)®, 0, 1, value); - break; - - case ARMV7M_BASEPRI: - buf_set_u32((uint8_t *)®, 8, 8, value); - break; - - case ARMV7M_FAULTMASK: - buf_set_u32((uint8_t *)®, 16, 1, value); - break; - - case ARMV7M_CONTROL: - buf_set_u32((uint8_t *)®, 24, 3, value); - break; - } - - cortexm_dap_write_coreregister_u32(target, reg, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); + case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: + cortexm_dap_write_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - LOG_DEBUG("write special reg %" PRIu32 " value 0x%" PRIx32 " ", regsel, value); + LOG_DEBUG("write special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, value); break; default: diff --git a/src/target/hla_target.c b/src/target/hla_target.c index f012664d7..725c2d2fe 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -97,38 +97,12 @@ static int adapter_load_core_reg_u32(struct target *target, (int)(regsel - ARMV7M_REGSEL_S0), *value); break; - case ARMV7M_PRIMASK: - case ARMV7M_BASEPRI: - case ARMV7M_FAULTMASK: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * in one Debug Core register. So say r0 and r2 docs; - * it was removed from r1 docs, but still works. - */ + case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: retval = adapter->layout->api->read_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, value); if (retval != ERROR_OK) return retval; - switch (regsel) { - case ARMV7M_PRIMASK: - *value = buf_get_u32((uint8_t *) value, 0, 1); - break; - - case ARMV7M_BASEPRI: - *value = buf_get_u32((uint8_t *) value, 8, 8); - break; - - case ARMV7M_FAULTMASK: - *value = buf_get_u32((uint8_t *) value, 16, 1); - break; - - case ARMV7M_CONTROL: - *value = buf_get_u32((uint8_t *) value, 24, 3); - break; - } - - LOG_DEBUG("load from special reg %" PRIu32 " value 0x%" PRIx32 "", - regsel, *value); + LOG_DEBUG("load from special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, *value); break; default: @@ -142,7 +116,6 @@ static int adapter_store_core_reg_u32(struct target *target, uint32_t regsel, uint32_t value) { int retval; - uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); struct hl_interface_s *adapter = target_to_adapter(target); @@ -186,38 +159,10 @@ static int adapter_store_core_reg_u32(struct target *target, (int)(regsel - ARMV7M_REGSEL_S0), value); break; - case ARMV7M_PRIMASK: - case ARMV7M_BASEPRI: - case ARMV7M_FAULTMASK: - case ARMV7M_CONTROL: - /* Cortex-M3 packages these four registers as bitfields - * in one Debug Core register. So say r0 and r2 docs; - * it was removed from r1 docs, but still works. - */ - - adapter->layout->api->read_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, ®); - - switch (regsel) { - case ARMV7M_PRIMASK: - buf_set_u32((uint8_t *) ®, 0, 1, value); - break; - - case ARMV7M_BASEPRI: - buf_set_u32((uint8_t *) ®, 8, 8, value); - break; - - case ARMV7M_FAULTMASK: - buf_set_u32((uint8_t *) ®, 16, 1, value); - break; - - case ARMV7M_CONTROL: - buf_set_u32((uint8_t *) ®, 24, 3, value); - break; - } - - adapter->layout->api->write_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, reg); + case ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL: + adapter->layout->api->write_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, value); - LOG_DEBUG("write special reg %" PRIu32 " value 0x%" PRIx32 " ", regsel, value); + LOG_DEBUG("write special reg PRIMASK/BASEPRI/FAULTMASK/CONTROL value 0x%" PRIx32, value); break; default: commit e4160bd42216d5e717822162e1dad83b1b7003a1 Author: Tomas Vanek <va...@fb...> Date: Wed Oct 14 16:52:09 2020 +0200 target/armv7m: rework Cortex-M register handling part 2 Make arm register id coherent with reg_list index. Without this reg_list[ARMV7M_R12] was possible but reg_list[ARMV7M_FPSCR] was out of bounds. Remove unused items from reg_list index. Change-Id: I84d3b5c496fc1839d07a5b74cb1fd1c3d4ff8989 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5862 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Christopher Head <ch...@za...> diff --git a/src/target/armv7m.c b/src/target/armv7m.c index ba60a98a6..177437391 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -254,6 +254,7 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); + assert(num == (int)r->number); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; @@ -293,6 +294,7 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, struct armv7m_common *armv7m = target_to_armv7m(target); assert(num < (int)armv7m->arm.core_cache->num_regs); + assert(num == (int)r->number); armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 8cd4df36f..bd10905b8 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -133,40 +133,6 @@ enum { ARMV7M_FAULTMASK, ARMV7M_CONTROL, - /* 32bit Floating-point registers */ - ARMV7M_S0, - ARMV7M_S1, - ARMV7M_S2, - ARMV7M_S3, - ARMV7M_S4, - ARMV7M_S5, - ARMV7M_S6, - ARMV7M_S7, - ARMV7M_S8, - ARMV7M_S9, - ARMV7M_S10, - ARMV7M_S11, - ARMV7M_S12, - ARMV7M_S13, - ARMV7M_S14, - ARMV7M_S15, - ARMV7M_S16, - ARMV7M_S17, - ARMV7M_S18, - ARMV7M_S19, - ARMV7M_S20, - ARMV7M_S21, - ARMV7M_S22, - ARMV7M_S23, - ARMV7M_S24, - ARMV7M_S25, - ARMV7M_S26, - ARMV7M_S27, - ARMV7M_S28, - ARMV7M_S29, - ARMV7M_S30, - ARMV7M_S31, - /* 64bit Floating-point registers */ ARMV7M_D0, ARMV7M_D1, @@ -185,10 +151,8 @@ enum { ARMV7M_D14, ARMV7M_D15, - /* Floating-point status registers */ - ARMV7M_FPSID, + /* Floating-point status register */ ARMV7M_FPSCR, - ARMV7M_FPEXC, ARMV7M_LAST_REG, }; ----------------------------------------------------------------------- Summary of changes: src/target/armv7m.c | 184 ++++++++++++++++++++++++++++++++++++------------ src/target/armv7m.h | 48 +++---------- src/target/cortex_m.c | 67 +++--------------- src/target/hla_target.c | 65 ++--------------- 4 files changed, 162 insertions(+), 202 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:06:30
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via efbc447ed8d49ef0fa0638faf13315d767208ab6 (commit) via f8453ae52cf336c337b7f135f10ed4afecf35a7c (commit) from 109dc1975f25a36a501811e48267b17d7dc19688 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit efbc447ed8d49ef0fa0638faf13315d767208ab6 Author: Tomas Vanek <va...@fb...> Date: Sun Oct 20 10:12:32 2019 +0200 target/armv7m: rework Cortex-M register handling part 1 Define a new enum with DCRSR.REGSEL selectors. Introduce armv7m_map_id_to_regsel() to unify mapping in one place. Use DCRSR.REGSEL selectors for low level register read/write. Change-Id: Ida0ccdfa9cdb1257a1900b8bfbf172b076374d39 Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5327 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Christopher Head <ch...@za...> diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 5e0694d8a..ba60a98a6 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -211,6 +211,40 @@ static int armv7m_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } +static uint32_t armv7m_map_id_to_regsel(unsigned int arm_reg_id) +{ + switch (arm_reg_id) { + case ARMV7M_R0 ... ARMV7M_R14: + case ARMV7M_PC: + case ARMV7M_xPSR: + case ARMV7M_MSP: + case ARMV7M_PSP: + /* NOTE: we "know" here that the register identifiers + * match the Cortex-M DCRSR.REGSEL selectors values + * for R0..R14, PC, xPSR, MSP, and PSP. + */ + return arm_reg_id; + + case ARMV7M_FPSCR: + return ARMV7M_REGSEL_FPSCR; + + case ARMV7M_D0 ... ARMV7M_D15: + return ARMV7M_REGSEL_S0 + 2 * (arm_reg_id - ARMV7M_D0); + + /* TODO: remove. This is temporary hack until packing/unpacking + * of special regs is moved to armv7m.c */ + case ARMV7M_PRIMASK: + case ARMV7M_BASEPRI: + case ARMV7M_FAULTMASK: + case ARMV7M_CONTROL: + return arm_reg_id; + + default: + LOG_ERROR("Bad register ID %u", arm_reg_id); + return arm_reg_id; + } +} + static int armv7m_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { @@ -223,22 +257,23 @@ static int armv7m_read_core_reg(struct target *target, struct reg *r, armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; + uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); + if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { /* map D0..D15 to S0..S31 */ - size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0); - retval = armv7m->load_core_reg_u32(target, regidx, ®_value); + retval = armv7m->load_core_reg_u32(target, regsel, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); - retval = armv7m->load_core_reg_u32(target, regidx + 1, ®_value); + retval = armv7m->load_core_reg_u32(target, regsel + 1, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value + 4, 0, 32, reg_value); } else { retval = armv7m->load_core_reg_u32(target, - armv7m_core_reg->num, ®_value); + regsel, ®_value); if (retval != ERROR_OK) return retval; buf_set_u32(armv7m->arm.core_cache->reg_list[num].value, 0, 32, reg_value); @@ -261,24 +296,24 @@ static int armv7m_write_core_reg(struct target *target, struct reg *r, armv7m_core_reg = armv7m->arm.core_cache->reg_list[num].arch_info; + uint32_t regsel = armv7m_map_id_to_regsel(armv7m_core_reg->num); + if ((armv7m_core_reg->num >= ARMV7M_D0) && (armv7m_core_reg->num <= ARMV7M_D15)) { /* map D0..D15 to S0..S31 */ - size_t regidx = ARMV7M_S0 + 2 * (armv7m_core_reg->num - ARMV7M_D0); - uint32_t t = buf_get_u32(value, 0, 32); - retval = armv7m->store_core_reg_u32(target, regidx, t); + retval = armv7m->store_core_reg_u32(target, regsel, t); if (retval != ERROR_OK) goto out_error; t = buf_get_u32(value + 4, 0, 32); - retval = armv7m->store_core_reg_u32(target, regidx + 1, t); + retval = armv7m->store_core_reg_u32(target, regsel + 1, t); if (retval != ERROR_OK) goto out_error; } else { uint32_t t = buf_get_u32(value, 0, 32); LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, t); - retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->num, t); + retval = armv7m->store_core_reg_u32(target, regsel, t); if (retval != ERROR_OK) goto out_error; } diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 01bf19e5c..8cd4df36f 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -34,36 +34,100 @@ extern const int armv7m_msp_reg_map[]; const char *armv7m_exception_string(int number); +/* Cortex-M DCRSR.REGSEL selectors */ +enum { + ARMV7M_REGSEL_R0, + ARMV7M_REGSEL_R1, + ARMV7M_REGSEL_R2, + ARMV7M_REGSEL_R3, + + ARMV7M_REGSEL_R4, + ARMV7M_REGSEL_R5, + ARMV7M_REGSEL_R6, + ARMV7M_REGSEL_R7, + + ARMV7M_REGSEL_R8, + ARMV7M_REGSEL_R9, + ARMV7M_REGSEL_R10, + ARMV7M_REGSEL_R11, + + ARMV7M_REGSEL_R12, + ARMV7M_REGSEL_R13, + ARMV7M_REGSEL_R14, + ARMV7M_REGSEL_PC = 15, + + ARMV7M_REGSEL_xPSR = 16, + ARMV7M_REGSEL_MSP, + ARMV7M_REGSEL_PSP, + + ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL = 0x14, + ARMV7M_REGSEL_FPSCR = 0x21, + + /* 32bit Floating-point registers */ + ARMV7M_REGSEL_S0 = 0x40, + ARMV7M_REGSEL_S1, + ARMV7M_REGSEL_S2, + ARMV7M_REGSEL_S3, + ARMV7M_REGSEL_S4, + ARMV7M_REGSEL_S5, + ARMV7M_REGSEL_S6, + ARMV7M_REGSEL_S7, + ARMV7M_REGSEL_S8, + ARMV7M_REGSEL_S9, + ARMV7M_REGSEL_S10, + ARMV7M_REGSEL_S11, + ARMV7M_REGSEL_S12, + ARMV7M_REGSEL_S13, + ARMV7M_REGSEL_S14, + ARMV7M_REGSEL_S15, + ARMV7M_REGSEL_S16, + ARMV7M_REGSEL_S17, + ARMV7M_REGSEL_S18, + ARMV7M_REGSEL_S19, + ARMV7M_REGSEL_S20, + ARMV7M_REGSEL_S21, + ARMV7M_REGSEL_S22, + ARMV7M_REGSEL_S23, + ARMV7M_REGSEL_S24, + ARMV7M_REGSEL_S25, + ARMV7M_REGSEL_S26, + ARMV7M_REGSEL_S27, + ARMV7M_REGSEL_S28, + ARMV7M_REGSEL_S29, + ARMV7M_REGSEL_S30, + ARMV7M_REGSEL_S31, +}; + /* offsets into armv7m core register cache */ enum { /* for convenience, the first set of indices match - * the Cortex-M3/-M4 DCRSR selectors + * the Cortex-M DCRSR.REGSEL selectors */ - ARMV7M_R0, - ARMV7M_R1, - ARMV7M_R2, - ARMV7M_R3, - - ARMV7M_R4, - ARMV7M_R5, - ARMV7M_R6, - ARMV7M_R7, - - ARMV7M_R8, - ARMV7M_R9, - ARMV7M_R10, - ARMV7M_R11, - - ARMV7M_R12, - ARMV7M_R13, - ARMV7M_R14, - ARMV7M_PC = 15, - - ARMV7M_xPSR = 16, - ARMV7M_MSP, - ARMV7M_PSP, - - /* this next set of indices is arbitrary */ + ARMV7M_R0 = ARMV7M_REGSEL_R0, + ARMV7M_R1 = ARMV7M_REGSEL_R1, + ARMV7M_R2 = ARMV7M_REGSEL_R2, + ARMV7M_R3 = ARMV7M_REGSEL_R3, + + ARMV7M_R4 = ARMV7M_REGSEL_R4, + ARMV7M_R5 = ARMV7M_REGSEL_R5, + ARMV7M_R6 = ARMV7M_REGSEL_R6, + ARMV7M_R7 = ARMV7M_REGSEL_R7, + + ARMV7M_R8 = ARMV7M_REGSEL_R8, + ARMV7M_R9 = ARMV7M_REGSEL_R9, + ARMV7M_R10 = ARMV7M_REGSEL_R10, + ARMV7M_R11 = ARMV7M_REGSEL_R11, + + ARMV7M_R12 = ARMV7M_REGSEL_R12, + ARMV7M_R13 = ARMV7M_REGSEL_R13, + ARMV7M_R14 = ARMV7M_REGSEL_R14, + ARMV7M_PC = ARMV7M_REGSEL_PC, + + ARMV7M_xPSR = ARMV7M_REGSEL_xPSR, + ARMV7M_MSP = ARMV7M_REGSEL_MSP, + ARMV7M_PSP = ARMV7M_REGSEL_PSP, + + /* following indices are arbitrary, do not match DCRSR.REGSEL selectors */ ARMV7M_PRIMASK, ARMV7M_BASEPRI, ARMV7M_FAULTMASK, @@ -137,7 +201,7 @@ enum { }; #define ARMV7M_NUM_CORE_REGS (ARMV7M_xPSR + 1) -#define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_NUM_CORE_REGS + 6) +#define ARMV7M_NUM_CORE_REGS_NOFP (ARMV7M_CONTROL + 1) #define ARMV7M_COMMON_MAGIC 0x2A452A45 @@ -159,8 +223,8 @@ struct armv7m_common { struct armv7m_trace_config trace_config; /* Direct processor core register read and writes */ - int (*load_core_reg_u32)(struct target *target, uint32_t num, uint32_t *value); - int (*store_core_reg_u32)(struct target *target, uint32_t num, uint32_t value); + int (*load_core_reg_u32)(struct target *target, uint32_t regsel, uint32_t *value); + int (*store_core_reg_u32)(struct target *target, uint32_t regsel, uint32_t value); int (*examine_debug_reason)(struct target *target); int (*post_debug_entry)(struct target *target); diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 0c1a99fc0..4df903e66 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1607,29 +1607,25 @@ void cortex_m_enable_watchpoints(struct target *target) } static int cortex_m_load_core_reg_u32(struct target *target, - uint32_t num, uint32_t *value) + uint32_t regsel, uint32_t *value) { int retval; - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (num) { - case 0 ... 18: + switch (regsel) { + case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: /* read a normal core register */ - retval = cortexm_dap_read_coreregister_u32(target, value, num); + retval = cortexm_dap_read_coreregister_u32(target, value, regsel); if (retval != ERROR_OK) { LOG_ERROR("JTAG failure %i", retval); return ERROR_JTAG_DEVICE_ERROR; } - LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value); + LOG_DEBUG("load from core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); break; - case ARMV7M_FPSCR: + case ARMV7M_REGSEL_FPSCR: /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRSR, 0x21); + retval = target_write_u32(target, DCB_DCRSR, ARMV7M_REGSEL_FPSCR); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, DCB_DCRDR, value); @@ -1638,16 +1634,16 @@ static int cortex_m_load_core_reg_u32(struct target *target, LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); break; - case ARMV7M_S0 ... ARMV7M_S31: + case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: /* Floating-point Status and Registers */ - retval = target_write_u32(target, DCB_DCRSR, num - ARMV7M_S0 + 0x40); + retval = target_write_u32(target, DCB_DCRSR, regsel); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, - (int)(num - ARMV7M_S0), *value); + (int)(regsel - ARMV7M_REGSEL_S0), *value); break; case ARMV7M_PRIMASK: @@ -1658,9 +1654,9 @@ static int cortex_m_load_core_reg_u32(struct target *target, * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ - cortexm_dap_read_coreregister_u32(target, value, 20); + cortexm_dap_read_coreregister_u32(target, value, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - switch (num) { + switch (regsel) { case ARMV7M_PRIMASK: *value = buf_get_u32((uint8_t *)value, 0, 1); break; @@ -1678,7 +1674,7 @@ static int cortex_m_load_core_reg_u32(struct target *target, break; } - LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", (int)num, *value); + LOG_DEBUG("load from special reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); break; default: @@ -1689,51 +1685,47 @@ static int cortex_m_load_core_reg_u32(struct target *target, } static int cortex_m_store_core_reg_u32(struct target *target, - uint32_t num, uint32_t value) + uint32_t regsel, uint32_t value) { int retval; uint32_t reg; struct armv7m_common *armv7m = target_to_armv7m(target); - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (num) { - case 0 ... 18: - retval = cortexm_dap_write_coreregister_u32(target, value, num); + switch (regsel) { + case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: + retval = cortexm_dap_write_coreregister_u32(target, value, regsel); if (retval != ERROR_OK) { struct reg *r; LOG_ERROR("JTAG failure"); - r = armv7m->arm.core_cache->reg_list + num; + r = armv7m->arm.core_cache->reg_list + regsel; /* TODO: don't use regsel as register index */ r->dirty = r->valid; return ERROR_JTAG_DEVICE_ERROR; } - LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value); + LOG_DEBUG("write core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, value); break; - case ARMV7M_FPSCR: + case ARMV7M_REGSEL_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, DCB_DCRSR, 0x21 | (1<<16)); + retval = target_write_u32(target, DCB_DCRSR, ARMV7M_REGSEL_FPSCR | DCRSR_WnR); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); break; - case ARMV7M_S0 ... ARMV7M_S31: + case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, DCB_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, DCB_DCRSR, (num - ARMV7M_S0 + 0x40) | (1<<16)); + retval = target_write_u32(target, DCB_DCRSR, regsel | DCRSR_WnR); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, - (int)(num - ARMV7M_S0), value); + (int)(regsel - ARMV7M_REGSEL_S0), value); break; case ARMV7M_PRIMASK: @@ -1744,9 +1736,9 @@ static int cortex_m_store_core_reg_u32(struct target *target, * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ - cortexm_dap_read_coreregister_u32(target, ®, 20); + cortexm_dap_read_coreregister_u32(target, ®, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - switch (num) { + switch (regsel) { case ARMV7M_PRIMASK: buf_set_u32((uint8_t *)®, 0, 1, value); break; @@ -1764,9 +1756,9 @@ static int cortex_m_store_core_reg_u32(struct target *target, break; } - cortexm_dap_write_coreregister_u32(target, reg, 20); + cortexm_dap_write_coreregister_u32(target, reg, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL); - LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); + LOG_DEBUG("write special reg %" PRIu32 " value 0x%" PRIx32 " ", regsel, value); break; default: diff --git a/src/target/hla_target.c b/src/target/hla_target.c index c02cbb643..f012664d7 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -51,7 +51,7 @@ static inline struct hl_interface_s *target_to_adapter(struct target *target) } static int adapter_load_core_reg_u32(struct target *target, - uint32_t num, uint32_t *value) + uint32_t regsel, uint32_t *value) { int retval; struct hl_interface_s *adapter = target_to_adapter(target); @@ -62,21 +62,21 @@ static int adapter_load_core_reg_u32(struct target *target, * in the v7m header match the Cortex-M3 Debug Core Register * Selector values for R0..R15, xPSR, MSP, and PSP. */ - switch (num) { - case 0 ... 18: + switch (regsel) { + case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: /* read a normal core register */ - retval = adapter->layout->api->read_reg(adapter->handle, num, value); + retval = adapter->layout->api->read_reg(adapter->handle, regsel, value); if (retval != ERROR_OK) { LOG_ERROR("JTAG failure %i", retval); return ERROR_JTAG_DEVICE_ERROR; } - LOG_DEBUG("load from core reg %i value 0x%" PRIx32 "", (int)num, *value); + LOG_DEBUG("load from core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, *value); break; - case ARMV7M_FPSCR: + case ARMV7M_REGSEL_FPSCR: /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33); + retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); @@ -85,16 +85,16 @@ static int adapter_load_core_reg_u32(struct target *target, LOG_DEBUG("load from FPSCR value 0x%" PRIx32, *value); break; - case ARMV7M_S0 ... ARMV7M_S31: + case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: /* Floating-point Status and Registers */ - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, num-ARMV7M_S0+64); + retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; LOG_DEBUG("load from FPU reg S%d value 0x%" PRIx32, - (int)(num - ARMV7M_S0), *value); + (int)(regsel - ARMV7M_REGSEL_S0), *value); break; case ARMV7M_PRIMASK: @@ -105,11 +105,11 @@ static int adapter_load_core_reg_u32(struct target *target, * in one Debug Core register. So say r0 and r2 docs; * it was removed from r1 docs, but still works. */ - retval = adapter->layout->api->read_reg(adapter->handle, 20, value); + retval = adapter->layout->api->read_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, value); if (retval != ERROR_OK) return retval; - switch (num) { + switch (regsel) { case ARMV7M_PRIMASK: *value = buf_get_u32((uint8_t *) value, 0, 1); break; @@ -127,8 +127,8 @@ static int adapter_load_core_reg_u32(struct target *target, break; } - LOG_DEBUG("load from special reg %i value 0x%" PRIx32 "", - (int)num, *value); + LOG_DEBUG("load from special reg %" PRIu32 " value 0x%" PRIx32 "", + regsel, *value); break; default: @@ -139,7 +139,7 @@ static int adapter_load_core_reg_u32(struct target *target, } static int adapter_store_core_reg_u32(struct target *target, - uint32_t num, uint32_t value) + uint32_t regsel, uint32_t value) { int retval; uint32_t reg; @@ -148,46 +148,42 @@ static int adapter_store_core_reg_u32(struct target *target, LOG_DEBUG("%s", __func__); - /* NOTE: we "know" here that the register identifiers used - * in the v7m header match the Cortex-M3 Debug Core Register - * Selector values for R0..R15, xPSR, MSP, and PSP. - */ - switch (num) { - case 0 ... 18: - retval = adapter->layout->api->write_reg(adapter->handle, num, value); + switch (regsel) { + case ARMV7M_REGSEL_R0 ... ARMV7M_REGSEL_PSP: + retval = adapter->layout->api->write_reg(adapter->handle, regsel, value); if (retval != ERROR_OK) { struct reg *r; LOG_ERROR("JTAG failure"); - r = armv7m->arm.core_cache->reg_list + num; + r = armv7m->arm.core_cache->reg_list + regsel; /* TODO: don't use regsel as register index */ r->dirty = r->valid; return ERROR_JTAG_DEVICE_ERROR; } - LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", (int)num, value); + LOG_DEBUG("write core reg %" PRIu32 " value 0x%" PRIx32 "", regsel, value); break; - case ARMV7M_FPSCR: + case ARMV7M_REGSEL_FPSCR: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, 33 | (1<<16)); + retval = target_write_u32(target, ARMV7M_SCS_DCRSR, ARMV7M_REGSEL_FPSCR | DCRSR_WnR); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPSCR value 0x%" PRIx32, value); break; - case ARMV7M_S0 ... ARMV7M_S31: + case ARMV7M_REGSEL_S0 ... ARMV7M_REGSEL_S31: /* Floating-point Status and Registers */ retval = target_write_u32(target, ARMV7M_SCS_DCRDR, value); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, ARMV7M_SCS_DCRSR, (num-ARMV7M_S0+64) | (1<<16)); + retval = target_write_u32(target, ARMV7M_SCS_DCRSR, regsel | DCRSR_WnR); if (retval != ERROR_OK) return retval; LOG_DEBUG("write FPU reg S%d value 0x%" PRIx32, - (int)(num - ARMV7M_S0), value); + (int)(regsel - ARMV7M_REGSEL_S0), value); break; case ARMV7M_PRIMASK: @@ -199,9 +195,9 @@ static int adapter_store_core_reg_u32(struct target *target, * it was removed from r1 docs, but still works. */ - adapter->layout->api->read_reg(adapter->handle, 20, ®); + adapter->layout->api->read_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, ®); - switch (num) { + switch (regsel) { case ARMV7M_PRIMASK: buf_set_u32((uint8_t *) ®, 0, 1, value); break; @@ -219,9 +215,9 @@ static int adapter_store_core_reg_u32(struct target *target, break; } - adapter->layout->api->write_reg(adapter->handle, 20, reg); + adapter->layout->api->write_reg(adapter->handle, ARMV7M_REGSEL_PMSK_BPRI_FLTMSK_CTRL, reg); - LOG_DEBUG("write special reg %i value 0x%" PRIx32 " ", (int)num, value); + LOG_DEBUG("write special reg %" PRIu32 " value 0x%" PRIx32 " ", regsel, value); break; default: commit f8453ae52cf336c337b7f135f10ed4afecf35a7c Author: Tomas Vanek <va...@fb...> Date: Sun Oct 20 09:40:34 2019 +0200 target, register: allow a register hidden from gdb and 'reg' cmd Introduce a 'hidden' flag in struct reg to support a register cache containing different views of same data: e.g. Cortex-M has primask, basepri, faultmask and control registers accessed as one word. With the hidden flag we can add an reg_list item corresponding to hw access without exposing the register to user level. All the struct reg are allocated with calloc() but one in xscale.c allocated by malloc(). Change this one to use calloc() as well to guarantee initial value hidden=false Change-Id: I8da9f5a5a60777ae7ef943a841307487bd80fc6f Signed-off-by: Tomas Vanek <va...@fb...> Reviewed-on: http://openocd.zylin.com/5325 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index bb4c1317d..792bbdcea 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1189,7 +1189,7 @@ static int gdb_get_registers_packet(struct connection *connection, return gdb_error(connection, retval); for (i = 0; i < reg_list_size; i++) { - if (reg_list[i] == NULL || reg_list[i]->exist == false) + if (reg_list[i] == NULL || reg_list[i]->exist == false || reg_list[i]->hidden) continue; reg_packet_size += DIV_ROUND_UP(reg_list[i]->size, 8) * 2; } @@ -1203,7 +1203,7 @@ static int gdb_get_registers_packet(struct connection *connection, reg_packet_p = reg_packet; for (i = 0; i < reg_list_size; i++) { - if (reg_list[i] == NULL || reg_list[i]->exist == false) + if (reg_list[i] == NULL || reg_list[i]->exist == false || reg_list[i]->hidden) continue; if (!reg_list[i]->valid) { retval = reg_list[i]->type->get(reg_list[i]); @@ -2176,7 +2176,7 @@ static int get_reg_features_list(struct target *target, char const **feature_lis *feature_list = calloc(1, sizeof(char *)); for (int i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false) + if (reg_list[i]->exist == false || reg_list[i]->hidden) continue; if (reg_list[i]->feature != NULL @@ -2270,7 +2270,7 @@ static int gdb_generate_target_description(struct target *target, char **tdesc_o int i; for (i = 0; i < reg_list_size; i++) { - if (reg_list[i]->exist == false) + if (reg_list[i]->exist == false || reg_list[i]->hidden) continue; if (strcmp(reg_list[i]->feature->name, features[current_feature])) diff --git a/src/target/register.h b/src/target/register.h index 7c53d6e16..1bae81183 100644 --- a/src/target/register.h +++ b/src/target/register.h @@ -134,6 +134,8 @@ struct reg { bool valid; /* When false, the register doesn't actually exist in the target. */ bool exist; + /* Hide the register from gdb and omit it in 'reg' cmd output */ + bool hidden; /* Size of the register in bits. */ uint32_t size; /* Used for generating XML description of registers. Can be set to NULL for diff --git a/src/target/target.c b/src/target/target.c index 9d4fe7721..3c1a6338e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3037,7 +3037,7 @@ COMMAND_HANDLER(handle_reg_command) for (i = 0, reg = cache->reg_list; i < cache->num_regs; i++, reg++, count++) { - if (reg->exist == false) + if (reg->exist == false || reg->hidden) continue; /* only print cached values if they are valid */ if (reg->valid) { diff --git a/src/target/xscale.c b/src/target/xscale.c index aaaed0ebb..b25999d3c 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -2882,7 +2882,7 @@ static void xscale_build_reg_cache(struct target *target) /* fill in values for the xscale reg cache */ (*cache_p)->name = "XScale registers"; (*cache_p)->next = NULL; - (*cache_p)->reg_list = malloc(num_regs * sizeof(struct reg)); + (*cache_p)->reg_list = calloc(num_regs, sizeof(struct reg)); (*cache_p)->num_regs = num_regs; for (i = 0; i < num_regs; i++) { ----------------------------------------------------------------------- Summary of changes: src/server/gdb_server.c | 8 ++-- src/target/armv7m.c | 53 +++++++++++++++++---- src/target/armv7m.h | 122 ++++++++++++++++++++++++++++++++++++------------ src/target/cortex_m.c | 64 +++++++++++-------------- src/target/hla_target.c | 62 ++++++++++++------------ src/target/register.h | 2 + src/target/target.c | 2 +- src/target/xscale.c | 2 +- 8 files changed, 202 insertions(+), 113 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-15 21:05:09
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 109dc1975f25a36a501811e48267b17d7dc19688 (commit) via 175f30e6952be5ca0e06b2e8753d8c72d6b90446 (commit) from 06c7a53f1fff20bcc4be9e63f83ae98664777f34 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 109dc1975f25a36a501811e48267b17d7dc19688 Author: Antonio Borneo <bor...@gm...> Date: Mon Nov 9 15:50:55 2020 +0100 flash/stmqspi: minor fixes on coding style Add space around operators; use BIT() macro in place of left shifting constant 1; remove space between cast operator and value; do not check a pointer before free() it; add parenthesis around parameters in macros; fix indentation using only TABs; remove line continuation '\' at code lines out of macros. Change-Id: I809e8ee72d7bfe49d0edf10afb36efe2458de77c Signed-off-by: Antonio Borneo <bor...@gm...> Fixes: e44539d66c89 ("Flash, FRAM and EEPROM driver for STM32 QUAD-/OCTOSPI interface") Reviewed-on: http://openocd.zylin.com/5932 Tested-by: jenkins Reviewed-by: Christopher Head <ch...@za...> diff --git a/src/flash/nor/sfdp.c b/src/flash/nor/sfdp.c index 02b4cedec..2fbc37d1f 100644 --- a/src/flash/nor/sfdp.c +++ b/src/flash/nor/sfdp.c @@ -81,7 +81,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, /* retrieve SFDP header */ memset(&header, 0, sizeof(header)); - retval = read_sfdp_block(bank, 0x0, sizeof(header) >> 2, (uint32_t *) &header); + retval = read_sfdp_block(bank, 0x0, sizeof(header) >> 2, (uint32_t *)&header); if (retval != ERROR_OK) return retval; LOG_DEBUG("header 0x%08" PRIx32 " 0x%08" PRIx32, header.signature, header.revision); @@ -105,7 +105,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, } memset(pheaders, 0, sizeof(struct sfdp_phdr) * nph); retval = read_sfdp_block(bank, sizeof(header), - (sizeof(struct sfdp_phdr) >> 2) * nph, (uint32_t *) pheaders); + (sizeof(struct sfdp_phdr) >> 2) * nph, (uint32_t *)pheaders); if (retval != ERROR_OK) goto err; @@ -132,7 +132,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, LOG_DEBUG("word %02d 0x%08X", j + 1, ptable[j]); if (id == SFDP_BASIC_FLASH) { - struct sfdp_basic_flash_param *table = (struct sfdp_basic_flash_param *) ptable; + struct sfdp_basic_flash_param *table = (struct sfdp_basic_flash_param *)ptable; uint16_t erase; if (words < 9) { @@ -215,7 +215,7 @@ int spi_sfdp(struct flash_bank *bank, struct flash_device *dev, LOG_INFO("device has to be switched to 4-byte addresses"); } } else if (id == SFDP_4BYTE_ADDR) { - struct sfdp_4byte_addr_param *table = (struct sfdp_4byte_addr_param *) ptable; + struct sfdp_4byte_addr_param *table = (struct sfdp_4byte_addr_param *)ptable; if (words >= (offsetof(struct sfdp_4byte_addr_param, erase_t1234) + sizeof(table->erase_t1234)) >> 2) { diff --git a/src/flash/nor/stmqspi.c b/src/flash/nor/stmqspi.c index 486ee53ce..11529f410 100644 --- a/src/flash/nor/stmqspi.c +++ b/src/flash/nor/stmqspi.c @@ -40,6 +40,7 @@ #endif #include "imp.h" +#include <helper/bits.h> #include <helper/time_support.h> #include <target/algorithm.h> #include <target/armv7m.h> @@ -137,7 +138,7 @@ /* 4-byte address in octo mode, else 3-byte address for read SFDP */ #define OCTOSPI_CCR_READ_SFDP(len) \ ((OCTOSPI_MODE_CCR & OCTOSPI_NO_DDTR & ~OCTOSPI_ADDR4 & OCTOSPI_NO_ALTB) | \ - ((len < 4) ? OCTOSPI_ADDR3 : OCTOSPI_ADDR4)) + (((len) < 4) ? OCTOSPI_ADDR3 : OCTOSPI_ADDR4)) #define OCTOSPI_CCR_WRITE_ENABLE \ ((OCTOSPI_MODE_CCR & OCTOSPI_NO_ADDR & OCTOSPI_NO_ALTB & OCTOSPI_NO_DATA)) @@ -153,17 +154,17 @@ #define SPI_ADSIZE (((stmqspi_info->saved_ccr >> SPI_ADSIZE_POS) & 0x3) + 1) -#define OPI_CMD(cmd) ((OPI_MODE ? ((((uint16_t) cmd)<<8) | (~cmd & 0xFFU)) : cmd)) +#define OPI_CMD(cmd) ((OPI_MODE ? ((((uint16_t)(cmd)) << 8) | (~(cmd) & 0xFFU)) : (cmd))) #define OCTOSPI_CMD(mode, ccr, ir) \ ({ \ retval = target_write_u32(target, io_base + OCTOSPI_CR, \ - OCTOSPI_MODE | mode); \ + OCTOSPI_MODE | (mode)); \ if (retval == ERROR_OK) \ retval = target_write_u32(target, io_base + OCTOSPI_TCR, \ (stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) | \ - ((OPI_MODE && (mode == OCTOSPI_READ_MODE)) ? \ - (OPI_DUMMY<<OCTOSPI_DCYC_POS) : 0)); \ + ((OPI_MODE && ((mode) == OCTOSPI_READ_MODE)) ? \ + (OPI_DUMMY << OCTOSPI_DCYC_POS) : 0)); \ if (retval == ERROR_OK) \ retval = target_write_u32(target, io_base + OCTOSPI_CCR, ccr); \ if (retval == ERROR_OK) \ @@ -177,7 +178,7 @@ static inline uint32_t h_to_le_32(uint32_t val) { uint32_t result; - h_u32_to_le((uint8_t *) &result, val); + h_u32_to_le((uint8_t *)&result, val); return result; } @@ -248,10 +249,10 @@ static int poll_busy(struct flash_bank *bank, int timeout) endtime = timeval_ms() + timeout; do { spi_sr = READ_REG(SPI_SR); - if ((spi_sr & (1U<<SPI_BUSY)) == 0) { + if ((spi_sr & BIT(SPI_BUSY)) == 0) { if (retval == ERROR_OK) { /* Clear transmit finished flag */ - retval = target_write_u32(target, io_base + SPI_FCR, (1U<<SPI_TCF)); + retval = target_write_u32(target, io_base + SPI_FCR, BIT(SPI_TCF)); } return retval; } else @@ -278,7 +279,7 @@ static int set_mm_mode(struct flash_bank *bank) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -321,7 +322,7 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -333,7 +334,7 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status) /* Read always two (for DTR mode) bytes per chip */ count = 2; retval = target_write_u32(target, io_base + SPI_DLR, - ((stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 2 * count : count) - 1); + ((stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 2 * count : count) - 1); if (retval != ERROR_OK) goto err; @@ -354,11 +355,11 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status) *status = 0; /* for debugging only */ - (void) READ_REG(SPI_SR); + (void)READ_REG(SPI_SR); for ( ; count > 0; --count) { - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (1U<<SPI_FSEL_FLASH)) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) + != BIT(SPI_FSEL_FLASH)) { /* get status of flash 1 in dual mode or flash 1 only mode */ retval = target_read_u8(target, io_base + SPI_DR, &data); if (retval != ERROR_OK) @@ -366,13 +367,12 @@ static int read_status_reg(struct flash_bank *bank, uint16_t *status) *status |= data; } - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (0U<<SPI_FSEL_FLASH)) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) != 0) { /* get status of flash 2 in dual mode or flash 2 only mode */ retval = target_read_u8(target, io_base + SPI_DR, &data); if (retval != ERROR_OK) goto err; - *status |= ((uint16_t) data) << 8; + *status |= ((uint16_t)data) << 8; } } @@ -417,7 +417,7 @@ static int qspi_write_enable(struct flash_bank *bank) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -435,7 +435,7 @@ static int qspi_write_enable(struct flash_bank *bank) if (retval != ERROR_OK) goto err; } - } else + } else retval = target_write_u32(target, io_base + QSPI_CCR, QSPI_CCR_WRITE_ENABLE); if (retval != ERROR_OK) goto err; @@ -452,8 +452,8 @@ static int qspi_write_enable(struct flash_bank *bank) goto err; /* Check write enabled for flash 1 */ - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (1U<<SPI_FSEL_FLASH))) + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) + != BIT(SPI_FSEL_FLASH)) if ((status & (SPIFLASH_WE_BIT | SPIFLASH_BSY_BIT)) != SPIFLASH_WE_BIT) { LOG_ERROR("Cannot write enable flash1. Status=0x%02" PRIx8, status & 0xFF); @@ -462,8 +462,7 @@ static int qspi_write_enable(struct flash_bank *bank) /* Check write enabled for flash 2 */ status >>= 8; - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (0U<<SPI_FSEL_FLASH))) + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) != 0) if ((status & (SPIFLASH_WE_BIT | SPIFLASH_BSY_BIT)) != SPIFLASH_WE_BIT) { LOG_ERROR("Cannot write enable flash2. Status=0x%02" PRIx8, status & 0xFF); @@ -546,8 +545,8 @@ COMMAND_HANDLER(stmqspi_handle_mass_erase_command) goto err; /* Check for command in progress for flash 1 */ - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (1U<<SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && + if (((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) + != BIT(SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && ((status & SPIFLASH_WE_BIT) != 0)) { LOG_ERROR("Mass erase command not accepted by flash1. Status=0x%02" PRIx8, status & 0xFF); @@ -557,8 +556,8 @@ COMMAND_HANDLER(stmqspi_handle_mass_erase_command) /* Check for command in progress for flash 2 */ status >>= 8; - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (0U<<SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && + if (((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) != 0) && + ((status & SPIFLASH_BSY_BIT) == 0) && ((status & SPIFLASH_WE_BIT) != 0)) { LOG_ERROR("Mass erase command not accepted by flash2. Status=0x%02" PRIx8, status & 0xFF); @@ -595,7 +594,7 @@ static int log2u(uint32_t word) int result; for (result = 0; (unsigned int) result < sizeof(uint32_t) * CHAR_BIT; result++) - if (word == (1UL<<result)) + if (word == BIT(result)) return result; return -1; @@ -613,7 +612,7 @@ COMMAND_HANDLER(stmqspi_handle_set) LOG_DEBUG("%s", __func__); - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; /* chip_erase_cmd, sectorsize and erase_cmd are optional */ if ((CMD_ARGC < 7) || (CMD_ARGC > 10)) @@ -715,14 +714,14 @@ COMMAND_HANDLER(stmqspi_handle_set) bank->size = stmqspi_info->dev.size_in_bytes << dual; io_base = stmqspi_info->io_base; - fsize = (READ_REG(SPI_DCR)>>SPI_FSIZE_POS) & ((1U<<SPI_FSIZE_LEN) - 1); + fsize = (READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1); if (retval != ERROR_OK) return retval; LOG_DEBUG("FSIZE = 0x%04x", fsize); - if (bank->size == (1U<<(fsize + 1))) + if (bank->size == BIT(fsize + 1)) LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1."); - else if (bank->size == (1U<<(fsize + 0))) + else if (bank->size == BIT(fsize + 0)) LOG_DEBUG("FSIZE in DCR(1) is off by one regarding actual capacity. Fix for silicon bug?"); else LOG_ERROR("FSIZE in DCR(1) doesn't match actual capacity."); @@ -749,12 +748,12 @@ COMMAND_HANDLER(stmqspi_handle_set) LOG_INFO("flash \'%s\' id = unknown\nchip size = %" PRIu32 "kbytes," " bank size = %" PRIu32 "kbytes", stmqspi_info->dev.name, stmqspi_info->dev.size_in_bytes / 1024, - (stmqspi_info->dev.size_in_bytes / 1024)<<dual); + (stmqspi_info->dev.size_in_bytes / 1024) << dual); else LOG_INFO("flash \'%s\' id = unknown\nchip size = %" PRIu32 "bytes," " bank size = %" PRIu32 "bytes", stmqspi_info->dev.name, stmqspi_info->dev.size_in_bytes, - stmqspi_info->dev.size_in_bytes<<dual); + stmqspi_info->dev.size_in_bytes << dual); stmqspi_info->probed = true; @@ -803,7 +802,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) if (num_read == 0) { /* nothing to read, then one command byte and for dual flash * an *even* number of data bytes to follow */ - if (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) { + if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) { if ((num_write & 1) == 0) { LOG_ERROR("number of data bytes to write must be even in dual mode"); return ERROR_COMMAND_SYNTAX_ERROR; @@ -811,7 +810,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) } } else { /* read mode, one command byte and up to four following address bytes */ - if (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) { + if (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) { if ((num_read & 1) != 0) { LOG_ERROR("number of bytes to read must be even in dual mode"); return ERROR_COMMAND_SYNTAX_ERROR; @@ -825,7 +824,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -838,7 +837,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) snprintf(output, sizeof(output), "spi: %02x ", cmd_byte); if (num_read == 0) { /* write, send cmd byte */ - retval = target_write_u32(target, io_base + SPI_DLR, ((uint32_t) num_write) - 2); + retval = target_write_u32(target, io_base + SPI_DLR, ((uint32_t)num_write) - 2); if (retval != ERROR_OK) goto err; @@ -858,7 +857,7 @@ COMMAND_HANDLER(stmqspi_handle_cmd) for (count = 3; count < CMD_ARGC; count++) { COMMAND_PARSE_NUMBER(u8, CMD_ARGV[count], data); snprintf(temp, sizeof(temp), "%02" PRIx8 " ", data); - retval = target_write_u8(target, io_base + SPI_DR, data); \ + retval = target_write_u8(target, io_base + SPI_DR, data); if (retval != ERROR_OK) goto err; strncat(output, temp, sizeof(output) - strlen(output) - 1); @@ -876,19 +875,19 @@ COMMAND_HANDLER(stmqspi_handle_cmd) strncat(output, "-> ", sizeof(output) - strlen(output) - 1); /* send cmd byte, if ADMODE indicates no address, this already triggers command */ - retval = target_write_u32(target, io_base + SPI_DLR, ((uint32_t) num_read) - 1); + retval = target_write_u32(target, io_base + SPI_DLR, ((uint32_t)num_read) - 1); if (retval != ERROR_OK) goto err; if (IS_OCTOSPI) retval = OCTOSPI_CMD(OCTOSPI_READ_MODE, (OCTOSPI_MODE_CCR & OCTOSPI_NO_DDTR & OCTOSPI_NO_ALTB & ~OCTOSPI_ADDR4 & ((num_write == 1) ? OCTOSPI_NO_ADDR : ~0U)) | - (((num_write - 2) & 0x3U)<<SPI_ADSIZE_POS), cmd_byte); + (((num_write - 2) & 0x3U) << SPI_ADSIZE_POS), cmd_byte); else retval = target_write_u32(target, io_base + QSPI_CCR, (QSPI_MODE & ~QSPI_DCYC_MASK & QSPI_NO_ALTB & ~QSPI_ADDR4 & ((num_write == 1) ? QSPI_NO_ADDR : ~0U)) | - ((QSPI_READ_MODE | (((num_write - 2) & 0x3U)<<SPI_ADSIZE_POS) | cmd_byte))); + ((QSPI_READ_MODE | (((num_write - 2) & 0x3U) << SPI_ADSIZE_POS) | cmd_byte))); if (retval != ERROR_OK) goto err; @@ -957,8 +956,8 @@ static int qspi_erase_sector(struct flash_bank *bank, unsigned int sector) /* Check for command in progress for flash 1 */ /* If BSY and WE are already cleared the erase did probably complete already */ - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (1U<<SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && + if (((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) + != BIT(SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && ((status & SPIFLASH_WE_BIT) != 0)) { LOG_ERROR("Sector erase command not accepted by flash1. Status=0x%02" PRIx8, status & 0xFF); @@ -969,8 +968,8 @@ static int qspi_erase_sector(struct flash_bank *bank, unsigned int sector) /* Check for command in progress for flash 2 */ /* If BSY and WE are already cleared the erase did probably complete already */ status >>= 8; - if (((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | (1U<<SPI_FSEL_FLASH))) - != (0U<<SPI_FSEL_FLASH)) && ((status & SPIFLASH_BSY_BIT) == 0) && + if (((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) != 0) && + ((status & SPIFLASH_BSY_BIT) == 0) && ((status & SPIFLASH_WE_BIT) != 0)) { LOG_ERROR("Sector erase command not accepted by flash2. Status=0x%02" PRIx8, status & 0xFF); @@ -1084,7 +1083,7 @@ static int stmqspi_blank_check(struct flash_bank *bank) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -1150,7 +1149,7 @@ static int stmqspi_blank_check(struct flash_bank *bank) /* prepare QSPI/OCTOSPI_CCR register values */ retval = target_write_buffer(target, algorithm->address + codesize - sizeof(ccr_buffer), - sizeof(ccr_buffer), (uint8_t *) ccr_buffer); + sizeof(ccr_buffer), (uint8_t *)ccr_buffer); if (retval != ERROR_OK) goto err; @@ -1177,7 +1176,7 @@ static int stmqspi_blank_check(struct flash_bank *bank) retval = target_write_buffer(target, algorithm->address + codesize + index * sizeof(erase_check_info), - sizeof(erase_check_info), (uint8_t *) &erase_check_info); + sizeof(erase_check_info), (uint8_t *)&erase_check_info); if (retval != ERROR_OK) goto err; } @@ -1202,7 +1201,7 @@ static int stmqspi_blank_check(struct flash_bank *bank) for (index = 0; index < count; index++) { retval = target_read_buffer(target, algorithm->address + codesize + index * sizeof(erase_check_info), - sizeof(erase_check_info), (uint8_t *) &erase_check_info); + sizeof(erase_check_info), (uint8_t *)&erase_check_info); if (retval != ERROR_OK) goto err; @@ -1276,7 +1275,7 @@ static int qspi_verify(struct flash_bank *bank, uint8_t *buffer, pagesize = SPIFLASH_DEF_PAGESIZE; /* adjust size according to dual flash mode */ - pagesize = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? pagesize << 1 : pagesize; + pagesize = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? pagesize << 1 : pagesize; /* This will overlay the last 4 words of stmqspi/stmoctospi_crc32_code in target */ /* for read use the saved settings (memory mapped mode) but indirect read mode */ @@ -1307,7 +1306,7 @@ static int qspi_verify(struct flash_bank *bank, uint8_t *buffer, /* prepare QSPI/OCTOSPI_CCR register values */ retval = target_write_buffer(target, algorithm->address + codesize - sizeof(ccr_buffer), - sizeof(ccr_buffer), (uint8_t *) ccr_buffer); + sizeof(ccr_buffer), (uint8_t *)ccr_buffer); if (retval != ERROR_OK) goto err; @@ -1379,7 +1378,7 @@ static int qspi_read_write_block(struct flash_bank *bank, uint8_t *buffer, LOG_DEBUG("%s: offset=0x%08" PRIx32 " len=0x%08" PRIx32, __func__, offset, count); - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; /* see contrib/loaders/flash/stmqspi/stmqspi_read.S for src */ static const uint8_t stmqspi_read_code[] = { @@ -1412,7 +1411,7 @@ static int qspi_read_write_block(struct flash_bank *bank, uint8_t *buffer, h_to_le_32(OCTOSPI_MODE | OCTOSPI_READ_MODE), h_to_le_32(IS_OCTOSPI ? OCTOSPI_CCR_READ_STATUS : QSPI_CCR_READ_STATUS), h_to_le_32((stmqspi_info->saved_tcr & ~OCTOSPI_DCYC_MASK) | - (OPI_MODE ? (OPI_DUMMY<<OCTOSPI_DCYC_POS) : 0)), + (OPI_MODE ? (OPI_DUMMY << OCTOSPI_DCYC_POS) : 0)), h_to_le_32(OPI_CMD(SPIFLASH_READ_STATUS)), }, { @@ -1490,7 +1489,7 @@ static int qspi_read_write_block(struct flash_bank *bank, uint8_t *buffer, /* prepare QSPI/OCTOSPI_CCR register values */ retval = target_write_buffer(target, algorithm->address + codesize - sizeof(ccr_buffer), - sizeof(ccr_buffer), (uint8_t *) ccr_buffer); + sizeof(ccr_buffer), (uint8_t *)ccr_buffer); if (retval != ERROR_OK) goto err; @@ -1592,7 +1591,7 @@ static int stmqspi_read(struct flash_bank *bank, uint8_t *buffer, /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -1617,8 +1616,8 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer, LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, __func__, offset, count); - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; - octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & (1U<<OCTOSPI_DDTR)); + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; + octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & BIT(OCTOSPI_DDTR)); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -1639,9 +1638,9 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer, for (sector = 0; sector < bank->num_sectors; sector++) { /* Start offset in or before this sector? */ /* End offset in or behind this sector? */ - if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) - && ((offset + count - 1) >= bank->sectors[sector].offset) - && bank->sectors[sector].is_protected) { + if ((offset < (bank->sectors[sector].offset + bank->sectors[sector].size)) && + ((offset + count - 1) >= bank->sectors[sector].offset) && + bank->sectors[sector].is_protected) { LOG_ERROR("Flash sector %u protected", sector); return ERROR_FLASH_PROTECTED; } @@ -1655,7 +1654,7 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer, /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -1664,7 +1663,7 @@ static int stmqspi_write(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) return retval; - return qspi_read_write_block(bank, (uint8_t *) buffer, offset, count, true); + return qspi_read_write_block(bank, (uint8_t *)buffer, offset, count, true); } static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer, @@ -1680,8 +1679,8 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer, LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, __func__, offset, count); - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; - octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & (1U<<OCTOSPI_DDTR)); + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; + octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & BIT(OCTOSPI_DDTR)); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -1706,7 +1705,7 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer, /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -1715,7 +1714,7 @@ static int stmqspi_verify(struct flash_bank *bank, const uint8_t *buffer, if (retval != ERROR_OK) return retval; - return qspi_verify(bank, (uint8_t *) buffer, offset, count); + return qspi_verify(bank, (uint8_t *)buffer, offset, count); } /* Find appropriate dummy setting, in particular octo mode */ @@ -1726,18 +1725,18 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len) uint32_t io_base = stmqspi_info->io_base; uint8_t data; unsigned int dual, count; - bool flash1 = !(stmqspi_info->saved_cr & (1U<<SPI_FSEL_FLASH)); + bool flash1 = !(stmqspi_info->saved_cr & BIT(SPI_FSEL_FLASH)); int retval; const unsigned int max_bytes = 64; - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; LOG_DEBUG("%s: len=%d, dual=%u, flash1=%d", __func__, len, dual, flash1); /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - stmqspi_info->saved_cr | (1U<<SPI_ABORT)); + stmqspi_info->saved_cr | BIT(SPI_ABORT)); if (retval != ERROR_OK) goto err; @@ -1806,7 +1805,7 @@ static int find_sfdp_dummy(struct flash_bank *bank, int len) err: /* Abort operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); return retval; } @@ -1818,11 +1817,11 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, struct target *target = bank->target; struct stmqspi_flash_bank *stmqspi_info = bank->driver_priv; uint32_t io_base = stmqspi_info->io_base; - bool flash1 = !(stmqspi_info->saved_cr & (1U<<SPI_FSEL_FLASH)); + bool flash1 = !(stmqspi_info->saved_cr & BIT(SPI_FSEL_FLASH)); unsigned int dual, count, len, *dummy; int retval; - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; if (IS_OCTOSPI && (((stmqspi_info->saved_ccr >> SPI_DMODE_POS) & 0x7) > 3)) { /* in OCTO mode 4-byte address and (yet) unknown number of dummy clocks */ @@ -1840,7 +1839,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, len = 3; /* use sfdp_dummy1/2 according to currently selected flash */ - dummy = (stmqspi_info->saved_cr & (1U<<SPI_FSEL_FLASH)) ? + dummy = (stmqspi_info->saved_cr & BIT(SPI_FSEL_FLASH)) ? &stmqspi_info->sfdp_dummy2 : &stmqspi_info->sfdp_dummy1; /* according to SFDP standard, there should always be 8 dummy *CLOCKS* @@ -1859,7 +1858,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - stmqspi_info->saved_cr | (1U<<SPI_ABORT)); + stmqspi_info->saved_cr | BIT(SPI_ABORT)); if (retval != ERROR_OK) goto err; @@ -1894,7 +1893,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, /* dummy clocks */ for (count = *dummy << dual; count > 0; --count) { - retval = target_read_u8(target, io_base + SPI_DR, (uint8_t *) buffer); + retval = target_read_u8(target, io_base + SPI_DR, (uint8_t *)buffer); if (retval != ERROR_OK) goto err; } @@ -1929,7 +1928,7 @@ static int read_sfdp_block(struct flash_bank *bank, uint32_t addr, LOG_DEBUG("raw SFDP data 0x%08" PRIx32, *buffer); /* endian correction, sfdp data is always le uint32_t based */ - *buffer = le_to_h_u32((uint8_t *) buffer); + *buffer = le_to_h_u32((uint8_t *)buffer); buffer++; } @@ -1961,7 +1960,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2) for (type = (IS_OCTOSPI && OPI_MODE) ? 1 : 0; type < 2 ; type++) { /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) goto err; @@ -1978,7 +1977,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2) /* Read at most 16 bytes per chip */ count = 16; retval = target_write_u32(target, io_base + SPI_DLR, - (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH) ? count * 2 : count) - 1); + (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH) ? count * 2 : count) - 1); if (retval != ERROR_OK) goto err; @@ -2014,29 +2013,29 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2) } /* for debugging only */ - (void) READ_REG(SPI_SR); + (void)READ_REG(SPI_SR); /* Read ID from Data Register */ for (len1 = 0, len2 = 0; count > 0; --count) { - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != (1U<<SPI_FSEL_FLASH)) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | + BIT(SPI_FSEL_FLASH))) != BIT(SPI_FSEL_FLASH)) { retval = target_read_u8(target, io_base + SPI_DR, &byte); if (retval != ERROR_OK) goto err; /* collect 3 bytes without continuation codes */ if ((byte != 0x7F) && (len1 < 3)) { - *id1 = (*id1 >> 8) | ((uint32_t) byte) << 16; + *id1 = (*id1 >> 8) | ((uint32_t)byte) << 16; len1++; } } - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != 0) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | + BIT(SPI_FSEL_FLASH))) != 0) { retval = target_read_u8(target, io_base + SPI_DR, &byte); if (retval != ERROR_OK) goto err; /* collect 3 bytes without continuation codes */ if ((byte != 0x7F) && (len2 < 3)) { - *id2 = (*id2 >> 8) | ((uint32_t) byte) << 16; + *id2 = (*id2 >> 8) | ((uint32_t)byte) << 16; len2++; } } @@ -2047,8 +2046,8 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2) break; } - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != (1U<<SPI_FSEL_FLASH)) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | + BIT(SPI_FSEL_FLASH))) != BIT(SPI_FSEL_FLASH)) { if ((*id1 == 0x000000) || (*id1 == 0xFFFFFF)) { /* no id retrieved, so id must be set manually */ LOG_INFO("No id from flash1"); @@ -2056,8 +2055,7 @@ static int read_flash_id(struct flash_bank *bank, uint32_t *id1, uint32_t *id2) } } - if ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != (0U<<SPI_FSEL_FLASH)) { + if ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | BIT(SPI_FSEL_FLASH))) != 0) { if ((*id2 == 0x000000) || (*id2 == 0xFFFFFF)) { /* no id retrieved, so id must be set manually */ LOG_INFO("No id from flash2"); @@ -2085,8 +2083,7 @@ static int stmqspi_probe(struct flash_bank *bank) if (stmqspi_info->probed) { bank->size = 0; bank->num_sectors = 0; - if (bank->sectors) - free(bank->sectors); + free(bank->sectors); bank->sectors = NULL; memset(&stmqspi_info->dev, 0, sizeof(stmqspi_info->dev)); stmqspi_info->sfdp_dummy1 = 0; @@ -2096,7 +2093,7 @@ static int stmqspi_probe(struct flash_bank *bank) /* Abort any previous operation */ retval = target_write_u32(target, io_base + SPI_CR, - READ_REG(SPI_CR) | (1U<<SPI_ABORT)); + READ_REG(SPI_CR) | BIT(SPI_ABORT)); if (retval != ERROR_OK) return retval; @@ -2133,7 +2130,7 @@ static int stmqspi_probe(struct flash_bank *bank) if (IS_OCTOSPI) { uint32_t mtyp; - mtyp = ((READ_REG(OCTOSPI_DCR1) & OCTOSPI_MTYP_MASK))>>OCTOSPI_MTYP_POS; + mtyp = ((READ_REG(OCTOSPI_DCR1) & OCTOSPI_MTYP_MASK)) >> OCTOSPI_MTYP_POS; if (retval == ERROR_OK) stmqspi_info->saved_tcr = READ_REG(OCTOSPI_TCR); if (retval == ERROR_OK) @@ -2167,8 +2164,8 @@ static int stmqspi_probe(struct flash_bank *bank) } } - dual = (stmqspi_info->saved_cr & (1U<<SPI_DUAL_FLASH)) ? 1 : 0; - octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & (1U<<OCTOSPI_DDTR)); + dual = (stmqspi_info->saved_cr & BIT(SPI_DUAL_FLASH)) ? 1 : 0; + octal_dtr = IS_OCTOSPI && (stmqspi_info->saved_ccr & BIT(OCTOSPI_DDTR)); if (dual || octal_dtr) bank->write_start_alignment = bank->write_end_alignment = 2; else @@ -2207,7 +2204,7 @@ static int stmqspi_probe(struct flash_bank *bank) uint32_t saved_cr = stmqspi_info->saved_cr; /* select flash1 */ - stmqspi_info->saved_cr = stmqspi_info->saved_cr & ~(1U<<SPI_FSEL_FLASH); + stmqspi_info->saved_cr = stmqspi_info->saved_cr & ~BIT(SPI_FSEL_FLASH); retval = spi_sfdp(bank, &temp, &read_sfdp_block); /* restore saved_cr */ @@ -2265,7 +2262,7 @@ static int stmqspi_probe(struct flash_bank *bank) uint32_t saved_cr = stmqspi_info->saved_cr; /* select flash2 */ - stmqspi_info->saved_cr = stmqspi_info->saved_cr | (1U<<SPI_FSEL_FLASH); + stmqspi_info->saved_cr = stmqspi_info->saved_cr | BIT(SPI_FSEL_FLASH); retval = spi_sfdp(bank, &temp, &read_sfdp_block); /* restore saved_cr */ @@ -2304,14 +2301,14 @@ static int stmqspi_probe(struct flash_bank *bank) /* Set correct size value */ bank->size = stmqspi_info->dev.size_in_bytes << dual; - fsize = ((READ_REG(SPI_DCR)>>SPI_FSIZE_POS) & ((1U<<SPI_FSIZE_LEN) - 1)); + fsize = ((READ_REG(SPI_DCR) >> SPI_FSIZE_POS) & (BIT(SPI_FSIZE_LEN) - 1)); if (retval != ERROR_OK) goto err; LOG_DEBUG("FSIZE = 0x%04x", fsize); - if (bank->size == (1U<<(fsize + 1))) + if (bank->size == BIT((fsize + 1))) LOG_DEBUG("FSIZE in DCR(1) matches actual capacity. Beware of silicon bug in H7, L4+, MP1."); - else if (bank->size == (1U<<(fsize + 0))) + else if (bank->size == BIT((fsize + 0))) LOG_DEBUG("FSIZE in DCR(1) is off by one regarding actual capacity. Fix for silicon bug?"); else LOG_ERROR("FSIZE in DCR(1) doesn't match actual capacity."); @@ -2380,10 +2377,10 @@ static int get_stmqspi_info(struct flash_bank *bank, char *buf, int buf_size) ", read = 0x%02" PRIx8 ", qread = 0x%02" PRIx8 ", pprog = 0x%02" PRIx8 ", mass_erase = 0x%02" PRIx8 ", sector size = %" PRIu32 "%sbytes, sector_erase = 0x%02" PRIx8 ")", - ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != (1U<<SPI_FSEL_FLASH)) ? "1" : "", - ((stmqspi_info->saved_cr & ((1U<<SPI_DUAL_FLASH) | - (1U<<SPI_FSEL_FLASH))) != (0U<<SPI_FSEL_FLASH)) ? "2" : "", + ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | + BIT(SPI_FSEL_FLASH))) != BIT(SPI_FSEL_FLASH)) ? "1" : "", + ((stmqspi_info->saved_cr & (BIT(SPI_DUAL_FLASH) | + BIT(SPI_FSEL_FLASH))) != 0) ? "2" : "", stmqspi_info->dev.name, stmqspi_info->dev.device_id, bank->size / 4096 ? bank->size / 1024 : bank->size, bank->size / 4096 ? "k" : "", stmqspi_info->dev.pagesize, diff --git a/src/flash/nor/stmqspi.h b/src/flash/nor/stmqspi.h index d8510ab19..85da25f09 100644 --- a/src/flash/nor/stmqspi.h +++ b/src/flash/nor/stmqspi.h @@ -51,7 +51,7 @@ #define SPI_DMODE_POS 24 /* bit position of DMODE */ #define QSPI_DCYC_POS 18 /* bit position of DCYC */ #define QSPI_DCYC_LEN 5 /* width of DCYC field */ -#define QSPI_DCYC_MASK (((1U<<QSPI_DCYC_LEN) - 1)<<QSPI_DCYC_POS) +#define QSPI_DCYC_MASK ((BIT(QSPI_DCYC_LEN) - 1) << QSPI_DCYC_POS) #define SPI_ADSIZE_POS 12 /* bit position of ADSIZE */ #define QSPI_WRITE_MODE 0x00000000U /* indirect write mode */ @@ -62,8 +62,8 @@ #define QSPI_NO_DATA (~0x03000000U) /* no data */ #define QSPI_NO_ALTB (~QSPI_ALTB_MODE) /* no alternate */ #define QSPI_NO_ADDR (~0x00000C00U) /* no address */ -#define QSPI_ADDR3 (0x2U<<SPI_ADSIZE_POS) /* 3 byte address */ -#define QSPI_ADDR4 (0x3U<<SPI_ADSIZE_POS) /* 4 byte address */ +#define QSPI_ADDR3 (0x2U << SPI_ADSIZE_POS) /* 3 byte address */ +#define QSPI_ADDR4 (0x3U << SPI_ADSIZE_POS) /* 4 byte address */ /* OCTOSPI register offsets */ #define OCTOSPI_CR (0x000) /* Control register */ @@ -92,7 +92,7 @@ /* additional fields in OCTOSPI_DCR1 */ #define OCTOSPI_MTYP_POS (24) /* bit position of MTYP */ #define OCTOSPI_MTYP_LEN (3) /* width of MTYP field */ -#define OCTOSPI_MTYP_MASK (((1U<<OCTOSPI_MTYP_LEN) - 1)<<OCTOSPI_MTYP_POS) +#define OCTOSPI_MTYP_MASK ((BIT(OCTOSPI_MTYP_LEN) - 1) << OCTOSPI_MTYP_POS) /* fields in OCTOSPI_CCR */ #define OCTOSPI_ALTB_MODE 0x001F0000U /* alternate byte mode */ @@ -100,17 +100,17 @@ #define OCTOSPI_NO_DATA (~0x0F000000U) /* no data */ #define OCTOSPI_NO_ALTB (~OCTOSPI_ALTB_MODE) /* no alternate */ #define OCTOSPI_NO_ADDR (~0x00000F00U) /* no address */ -#define OCTOSPI_ADDR3 (0x2U<<SPI_ADSIZE_POS) /* 3 byte address */ -#define OCTOSPI_ADDR4 (0x3U<<SPI_ADSIZE_POS) /* 4 byte address */ +#define OCTOSPI_ADDR3 (0x2U << SPI_ADSIZE_POS) /* 3 byte address */ +#define OCTOSPI_ADDR4 (0x3U << SPI_ADSIZE_POS) /* 4 byte address */ #define OCTOSPI_DQSEN 29 /* DQS enable */ #define OCTOSPI_DDTR 27 /* DTR for data */ -#define OCTOSPI_NO_DDTR (~(1U<<OCTOSPI_DDTR)) /* no DTR for data, but maybe still DQS */ +#define OCTOSPI_NO_DDTR (~BIT(OCTOSPI_DDTR)) /* no DTR for data, but maybe still DQS */ #define OCTOSPI_ISIZE_MASK (0x30) /* ISIZE field */ /* fields in OCTOSPI_TCR */ #define OCTOSPI_DCYC_POS 0 /* bit position of DCYC */ #define OCTOSPI_DCYC_LEN 5 /* width of DCYC field */ -#define OCTOSPI_DCYC_MASK (((1U<<OCTOSPI_DCYC_LEN) - 1)<<OCTOSPI_DCYC_POS) +#define OCTOSPI_DCYC_MASK ((BIT(OCTOSPI_DCYC_LEN) - 1) << OCTOSPI_DCYC_POS) #define IS_OCTOSPI (stmqspi_info->octo) #define SPI_CR (IS_OCTOSPI ? OCTOSPI_CR : QSPI_CR) diff --git a/src/target/target.c b/src/target/target.c index db759d9c3..9d4fe7721 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1154,7 +1154,7 @@ int target_run_read_async_algorithm(struct target *target, } LOG_DEBUG("offs 0x%zx count 0x%" PRIx32 " wp 0x%" PRIx32 " rp 0x%" PRIx32, - (size_t) (buffer - buffer_orig), count, wp, rp); + (size_t)(buffer - buffer_orig), count, wp, rp); if (wp == 0) { LOG_ERROR("flash read algorithm aborted by target"); commit 175f30e6952be5ca0e06b2e8753d8c72d6b90446 Author: Antonio Borneo <bor...@gm...> Date: Mon Nov 9 12:53:30 2020 +0100 tcl/board: rename board file ST b-l475e-iot01a Use the board file name as <company>_<name>.cfg Add the SPDX tag to workaround an error in checkpatch that fails to recognize as valid a patch that only changes a file name. Change-Id: I929cd9e5f9fe2e7386950643487534c9a5a05bc6 Signed-off-by: Antonio Borneo <bor...@gm...> Fixes: e44539d66c89 ("Flash, FRAM and EEPROM driver for STM32 QUAD-/OCTOSPI interface") Reviewed-on: http://openocd.zylin.com/5931 Reviewed-by: Tarek BOCHKATI <tar...@gm...> Tested-by: jenkins diff --git a/tcl/board/b-l475e-iot01a.cfg b/tcl/board/st_b-l475e-iot01a.cfg similarity index 97% rename from tcl/board/b-l475e-iot01a.cfg rename to tcl/board/st_b-l475e-iot01a.cfg index be411e49f..e75c99d7a 100644 --- a/tcl/board/b-l475e-iot01a.cfg +++ b/tcl/board/st_b-l475e-iot01a.cfg @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + # This is an B-L475E-IOT01A Discovery kit for IoT node with a single STM32L475VGT6 chip. # http://www.st.com/en/evaluation-tools/b-l475e-iot01a.html ----------------------------------------------------------------------- Summary of changes: src/flash/nor/sfdp.c | 8 +- src/flash/nor/stmqspi.c | 207 ++++++++++----------- src/flash/nor/stmqspi.h | 16 +- src/target/target.c | 2 +- .../{b-l475e-iot01a.cfg => st_b-l475e-iot01a.cfg} | 2 + 5 files changed, 117 insertions(+), 118 deletions(-) rename tcl/board/{b-l475e-iot01a.cfg => st_b-l475e-iot01a.cfg} (97%) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-11 21:23:10
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 06c7a53f1fff20bcc4be9e63f83ae98664777f34 (commit) from e44539d66c8929679321704768125df9ba7d5f67 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 06c7a53f1fff20bcc4be9e63f83ae98664777f34 Author: Kevin Yang <kan...@go...> Date: Wed Nov 4 10:39:29 2020 -0800 target/cortex_m: Change sleep to running state When the core is in sleep mode, the core is no longer retiring instructions. Cortext M remains in "unknown" state. This patch converts sleep mode to "running" state. Change-Id: I1e9b6c9be51fd0f1f6ce81af9b1f5f9f1f43c661 Signed-off-by: Kevin Yang <kan...@go...> Reviewed-on: http://openocd.zylin.com/5921 Reviewed-by: Tomas Vanek <va...@fb...> Tested-by: jenkins diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 08b3661ea..0c1a99fc0 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -656,13 +656,9 @@ static int cortex_m_poll(struct target *target) } } - /* REVISIT when S_SLEEP is set, it's in a Sleep or DeepSleep state. - * How best to model low power modes? - */ - if (target->state == TARGET_UNKNOWN) { - /* check if processor is retiring instructions */ - if (cortex_m->dcb_dhcsr & S_RETIRE_ST) { + /* check if processor is retiring instructions or sleeping */ + if (cortex_m->dcb_dhcsr & S_RETIRE_ST || cortex_m->dcb_dhcsr & S_SLEEP) { target->state = TARGET_RUNNING; retval = ERROR_OK; } diff --git a/src/target/target.h b/src/target/target.h index 44463b74f..b9ae2f78e 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -47,7 +47,7 @@ struct gdb_fileio_info; /* * TARGET_UNKNOWN = 0: we don't know anything about the target yet - * TARGET_RUNNING = 1: the target is executing user code + * TARGET_RUNNING = 1: the target is executing or ready to execute user code * TARGET_HALTED = 2: the target is not executing code, and ready to talk to the * debugger. on an xscale it means that the debug handler is executing * TARGET_RESET = 3: the target is being held in reset (only a temporary state, ----------------------------------------------------------------------- Summary of changes: src/target/cortex_m.c | 8 ++------ src/target/target.h | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-08 22:46:53
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via e44539d66c8929679321704768125df9ba7d5f67 (commit) from 475f42051e13d64bc4d1960306ad1d2ea3c7962a (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e44539d66c8929679321704768125df9ba7d5f67 Author: Andreas Bolsch <hyp...@gm...> Date: Wed Dec 21 10:35:58 2016 +0100 Flash, FRAM and EEPROM driver for STM32 QUAD-/OCTOSPI interface - write speed up to 150 kByte/s on STM32F469I-disco (due to SWD clock and USB connection), up to 1 MByte/s on Nucleo-F767ZI with external STLink-V3 or Nucleo-G474RE with two W25Q256FV in dual 4-line mode or STM32H73BI-Disco in octal mode - tested with STM32L476G-disco (64MBit flash, 3-byte addr), STM32F412G-Disco, STM32F469I-Disco, STM32F746G-Disco, and STM32L476G-Disco (all 128Mbit flash, 3-byte addr), STM32F723E-Disco, STM32F769I-Disco (512Mbit flash, 4-byte addr) STM32L4R9I-Disco, STM32L4P5G-Disco (512MBit octo-flash, DTR, 4-byte addr) STM32H745I-Disco, STM32H747I-Disco (two 512MBit flash, 4-byte addr) STM32H73BI-Disco, STM32H735G-Disco (512MBit octo-flash, DTR, 4-byte addr) - suitable cfg for Discovery boards included - limited parsing of SFDP data if flash device not hardcoded (tested only in single/quad mode as most devices either don't support SFDP at all or have empty(!) SFDP memory) - 'set' command for auto detection override (e. g. for EEPROMs) - 'cmd' command for arbitrary SPI commands (reconfiguration, testing etc.) - makefile for creation of binary loader files - tcl/board/stm32f469discovery.cfg superseded by stm32f469i-disco.cfg - tcl/board/stm32f7discovery.cfg removed as name is ambiguous (superseded by stm32f746g-disco.cfg vs. stm32f769i-disco.cfg) - dual 4-line mode tested on Nucleo-F767ZI, Nucleo-H743ZI and Nucleo-H7A3ZI-Q with two W25Q256FV, and on Nucleo-L496ZP-P and Nucleo-L4R5ZI with two W25Q128FV, sample cfg files included and on STM32H745I-Disco, STM32H747I-Disco, STM32H750B-Disco - read/verify/erase_check uses indirect read mode to work around silicon bug in H7, L4+ and MP1 memory mapped mode (last bytes not readable, accessing last bytes causes debug interface to hang) - octospi supported only in single/dual 1-line, 2-line, 4-line and single 8-line modes, (not in hyper flash mode) Requirements: GPIOs must be initialized appropriately, and SPI flash chip be configured appropriately (1-line ..., QPI, 4-byte addresses ...). This is board/chip specific, cf. included cfg files. The driver infers most parameters from current setting in CR, CCR, ... registers. Change-Id: I54858fbbe8758c3a5fe58812e93f5f39514704f8 Signed-off-by: Andreas Bolsch <hyp...@gm...> Reviewed-on: http://openocd.zylin.com/4321 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Tomas Vanek <va...@fb...> Reviewed-by: Christopher Head <ch...@za...> diff --git a/contrib/loaders/flash/stmqspi/Makefile b/contrib/loaders/flash/stmqspi/Makefile new file mode 100644 index 000000000..810c7e87c --- /dev/null +++ b/contrib/loaders/flash/stmqspi/Makefile @@ -0,0 +1,34 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +SRCS=stmqspi_erase_check.S stmqspi_crc32.S stmqspi_read.S stmqspi_write.S \ + stmoctospi_erase_check.S stmoctospi_crc32.S stmoctospi_read.S stmoctospi_write.S +OBJS=$(patsubst %.S,%.inc,$(SRCS)) + +CROSS_COMPILE ?= arm-none-eabi- + +CC=$(CROSS_COMPILE)gcc +OBJCOPY=$(CROSS_COMPILE)objcopy +OBJDUMP=$(CROSS_COMPILE)objdump +LD=$(CROSS_COMPILE)ld + +all: $(OBJS) + +%.o: %.S Makefile + $(CC) -Wall -Werror -Wa,-adhlmn -o $@ -c $< > $(@:.o=.lst) + @enscript -Easm -T 4 -G -o - $(@:.o=.lst) | ps2pdf - $(@:.o=.pdf) || true + +%.elf: %.o + $(LD) -s -defsym=_start=0 -o $@ $< + +%.bin: %.elf + $(OBJCOPY) -S -O binary $< $@ + +%.inc: %.bin + $(BIN2C) < $< > $@ + +clean: + -rm -f *.o *.elf *.lst *.pdf *.bin *.inc + +.PHONY: all clean + +.INTERMEDIATE: $(patsubst %.S,%.o,$(SRCS)) $(patsubst %.S,%.elf,$(SRCS)) $(patsubst %.S,%.bin,$(SRCS)) diff --git a/contrib/loaders/flash/stmqspi/gpio_conf_stm32.pl b/contrib/loaders/flash/stmqspi/gpio_conf_stm32.pl new file mode 100755 index 000000000..b7538640e --- /dev/null +++ b/contrib/loaders/flash/stmqspi/gpio_conf_stm32.pl @@ -0,0 +1,679 @@ +#!/usr/bin/perl +# +# Helper for generating GPIO setup for STM32F0, F4, F7, H7, L0, L1, L4, L4+ +# and F1 (for 'stmqspi' and 'cmspi' drivers). +# +# Each pin is configured by "PortAndBit:Conf:Speed" +# 'PortAndBit' specifies Port and bit number +# 'Conf' is one of 'AFx' (alternate), 'P' (output), 'IN' (input), +# (each optionally by 'P' (push-pull) or 'O' (open-drain)), +# (all optionally followed by 'UP' (pull-up), or 'DO' (pull-down)) +# 'Speed' is one of 'L' (low), 'M' (medium), 'H' (high), 'V' (very high) +# +# Port configuration can be given on command line as a single string (pins separated by commas) +# or via CubeMX generated file. The latter must consist of the quadspi.c / octospi.c and the +# corresponding header. The precise spelling in these files doesn't seem to be consistent, though ... +# +# Pins have to be ordered this way: +# - I2C: SDA, SCL +# - SPI (1 line): NCS, CLK, IO1/MISO, IO0/MOSI +# - DPI (2 lines): NCS, CLK, IO1/MISO, IO0/MOSI +# - QPI (4 lines): NCS, CLK, IO3/NHOLD, IO2/NWP, IO1/MISO, IO0/MOSI +# For dual flash: BK_1 first, then BK_2. If single NCS for both, omit NCS in BK_2 +# For octal flash: NCS, CLK, DQS, IO7 down to IO0 + +use strict; +use Getopt::Std; + +my $GPIO_BASE; +my $Conf; +my $STM32F1 = 0; + +# "Blue-Pill stm32f103cbt6 board w/ cmspi +#$STM32F1 = 1; +#$GPIO_BASE = 0x40010800; +#$Conf = "PB12:PP:M, PB13:PP:V, PB14:INUP:V, PB15:INUP:V"; +#$Conf = "PB12:PP:M, PB13:PP:V, PB14:INUP:V, PB01:INUP:V"; + +#$STM32F1 = 1; +#$GPIO_BASE = 0x40010800; +#$Conf = "PB07:INUP:V, PB06:INUP:V"; + +# mini-stm32f030f4p6 board w/ cmspi +#$GPIO_BASE = 0x48000000; +#$Conf = "PB01:PP:V, PA05:PP:V, PA06:INUP:V, PA07:INUP:V"; + +# stm32f407vet6 board w/ cmspi +#$GPIO_BASE = 0x40020000; +#$Conf = "PB00:PP:M, PB03:PP:V, PB04:INUP:V, PB05:INUP:V"; + +# stm32f412g-disco quad +#$GPIO_BASE = 0x40020000; +#$Conf = "PB02:AF09:V, PF09:AF10:V, PF08:AF10:V, PF07:AF09:V, PF06:AF09:V, PG06:AF10:V"; + +# stm32f413h-disco +#$GPIO_BASE = 0x40020000; +#$Conf = "PB02:AF09:V, PD13:AF09:V, PE02:AF09:V, PF09:AF10:V, PF08:AF10:V, PG06:AF10:V"; + +# stm32f469i-disco quad +#$GPIO_BASE = 0x40020000; +#$Conf = "PB06:AF10:V, PF10:AF09:V, PF09:AF10:V, PF08:AF10:V, PF07:AF09:V, PF06:AF09:V"; +# w/ cmspi +#$Conf = "PB06:PP:M, PF10:PP:V, PF06:INUP:V, PF07:INUP:V, PF09:INUP:V, PF08:INUP:V"; + +# stm32f723e-disco quad +#$GPIO_BASE = 0x40020000; +#$Conf = "PB06:AF10:V, PB02:AF09:V, PC10:AF09:V, PC09:AF09:V, PD13:AF09:V, PE02:AF09:V"; + +# stm32f746g-disco quad +#$GPIO_BASE = 0x40020000; +#Conf = "PB06:AF10:V, PB02:AF09:V, PD13:AF09:V, PE02:AF09:V, PD12:AF09:V, PD11:AF09:V"; +# w/ cmspi +#$Conf = "PB06:PP:M, PB02:PP:V, PD13:INUP:V, PE02:INUP:V, PD12:INUP:V, PD11:INUP:V"; + +# stm32f769i-disco quad +#$GPIO_BASE = 0x40020000; +#$Conf = "PB06:AF10:V, PB02:AF09:V, PC10:AF09:V, PC09:AF09:V, PD13:AF09:V, PE02:AF09:V"; +# w/ cmspi +#$Conf = "PB06:PP:M, PB02:PP:V, PD13:INUP:V, PE02:INUP:V, PC10:INUP:V, PC09:INUP:V, "; + +# b-l475e-iot01a quad +#$GPIO_BASE = 0x48000000; +#$Conf = "PE15:AF10:V, PE14:AF10:V, PE13:AF10:V, PE12:AF10:V, PE11:AF10:V, PE10:AF10:V"; + +# stm32l476g-disco quad +#$GPIO_BASE = 0x48000000; +#$Conf = "PE15:AF10:V, PE14:AF10:V, PE13:AF10:V, PE12:AF10:V, PE11:AF10:V, PE10:AF10:V"; + +# stm32l496g-disco quad +#$GPIO_BASE = 0x48000000; +#$Conf = "PA07:AF10:V, PA06:AF10:V, PA03:AF10:V, PB11:AF10:V, PB01:AF10:V, PB00:AF10:V"; + +# stm32l4r9i-disco octal +#$GPIO_BASE = 0x48000000; +#$Conf = "PG15:AF05:V, PG12:AF05:V, PG10:AF05:V, PG09:AF05:V, PH10:AF05:V, PH09:AF05:V, " +# . "PH08:AF05:V, PI11:AF05:V, PI10:AF05:V, PI09:AF05:V, PI06:AF05:V"; + +# stm32l4p5g-disco octal/octal +#$GPIO_BASE = 0x48000000; +#$Conf = "PA07:AF10:V, PA06:AF10:V, PC03:AF10:V, PD07:AF10:V, PD05:AF10:V, PD04:AF10:V, " +# . "PE13:AF10:V, PE12:AF10:V, PE11:AF10:V, PE10:AF10:V, PG06:AF03:V"; +#$Conf = "PF12:AF05:V, PF04:AF05:V, PF03:AF05:V, PF02:AF05:V, PF01:AF05:V, PF00:AF05:V, " +# . "PG12:AF05:V, PG10:AF05:V, PG09:AF05:V, PG01:AF05:V, PG00:AF05:V"; + +# nucleo-f767zi dual quad +#$GPIO_BASE = 0x40020000; +#$Conf = "PB06:AF10:V, PB02:AF09:V, PC11:AF09:V, PD13:AF09:V, PE02:AF09:V, PD12:AF09:V, " +# . "PD11:AF09:V, PE10:AF10:V, PE09:AF10:V, PE08:AF10:V, PE07:AF10:V"; +# w/ cmspi +#$Conf = "PB10:PPUP:M, PB02:PPUP:V, PD13:INPUP:V, PE02:INPUP:V, PD12:INPUP:V, PD11:INPUP:V"; +#$Conf = "PC11:PPUP:M, PB02:PPUP:V, PE10:INPUP:V, PE09:INPUP:V, PE08:INPUP:V, PE07:INPUP:V"; + +# nucleo-h743zi dual quad +#$GPIO_BASE = 0x58020000; +#$Conf = "PB10:AF09:V, PB02:AF09:V, PC11:AF09:V, PD13:AF09:V, PE02:AF09:V, PD12:AF09:V, " +# . "PD11:AF09:V, PE10:AF10:V, PE09:AF10:V, PE08:AF10:V, PE07:AF10:V"; +# w/ cmspi +#$Conf = "PB10:PPUP:M, PB02:PPUP:V, PD13:INPUP:V, PE02:INPUP:V, PD12:INPUP:V, PD11:INPUP:V"; +#$Conf = "PC11:PPUP:M, PB02:PPUP:V, PE10:INPUP:V, PE09:INPUP:V, PE08:INPUP:V, PE07:INPUP:V"; + +# nucleo-h7a3zi dual quad +#$GPIO_BASE = 0x58020000; +#$Conf = "PB10:AF09:V, PB02:AF09:V, PD13:AF09:V, PE02:AF09:V, PD12:AF09:V, PD11:AF09:V, " +# . "PC11:AF09:V, PE10:AF10:V, PD06:AF10:V, PE08:AF10:V, PE07:AF10:V"; +# w/ cmspi +#$Conf = "PB10:PPUP:M, PB02:PPUP:V, PD13:INPUP:V, PE02:INPUP:V, PD12:INPUP:V, PD11:INPUP:V"; +#$Conf = "PC11:PPUP:M, PB02:PPUP:V, PE10:INPUP:V, PD06:INPUP:V, PE08:INPUP:V, PE07:INPUP:V"; + +# nucleo-l4r5zi one dual quad single NCS +#$GPIO_BASE = 0x48000000; +#$Conf = "PA02:AF10:V, PE10:AF10:V, PD07:AF10:V, PD06:AF10:V, PD05:AF10:V, PD04:AF10:V, " +# . "PE15:AF10:V, PE14:AF10:V, PE13:AF10:V, PE12:AF10:V"; +# w/ cmspi +#$Conf = "PA02:PPUP:M, PE10:PPUP:V, PD07:INPDO:V, PD06:INPDO:V, PD05:INPDO:V, PD04:INPDO:V"; +#$Conf = "PA02:PPUP:M, PE10:PPUP:V, PE15:INPDO:V, PE14:INPDO:V, PE13:INPDO:V, PE12:INPDO:V"; + +# nucleo-l552ze-q dual quad with single NCS +#$GPIO_BASE = 0x42020000; +#$Conf = "PA02:AF10:V, PE10:AF10:V, PD07:AF10:V, PD06:AF10:V, PD05:AF10:V, PD04:AF10:V, " +# . "PE15:AF10:V, PE14:AF10:V, PE13:AF10:V, PE12:AF10:V"; +# w/ cmspi +#$Conf = "PA02:PPUP:M, PE10:PPUP:V, PD07:INPDO:V, PD06:INPDO:V, PD05:INPDO:V, PD04:INPDO:V"; +#$Conf = "PA02:PPUP:M, PE10:PPUP:V, PE15:INPDO:V, PE14:INPDO:V, PE13:INPDO:V, PE12:INPDO:V"; + +# nucleo-g071rb dual quad +#$GPIO_BASE = 0x50000000; +#$Conf = "PA00:PPUP:H, PA04:PPUP:V, PB03:INPUP:V, PA10:INPUP:V, PB11:INPUP:H, PB01:INPUP:H"; +#$Conf = "PA01:PPUP:H, PA04:PPUP:V, PA08:INPUP:V, PB14:INPUP:V, PB04:INPUP:V, PB05:INPUP:V"; + +# nucleo-g474re dual quad with single NCS +#$GPIO_BASE = 0x48000000; +#$Conf = "PB11:AF10:H, PB10:AF10:V, PA06:AF10:V, PA07:AF10:V, PB00:AF10:V, PB01:AF10:V, " +# . "PC04:AF10:V, PC03:AF10:V, PC02:AF10:V, PC01:AF10:V"; +# w/ cmspi +#$Conf = "PB11:PPUP:H, PB10:PPUP:V, PA06:INPUP:V, PA07:INPUP:V, PB00:INPUP:V, PB01:INPUP:V"; +#$Conf = "PB11:PPUP:H, PB10:PPUP:V, PC04:INPUP:V, PC03:INPUP:V, PC02:INPUP:V, PC01:INPUP:V"; + +# stm32h745i-disco dual quad with single NCS +#$GPIO_BASE = 0x58020000; +#$Conf = "PG06:AF10:H, PF10:AF09:V, PF06:AF09:V, PF07:AF09:V, PF09:AF10:V, PD11:AF09:V, " +# . "PG14:AF09:H, PG09:AF09:V, PH03:AF09:V, PH02:AF09:V"; + +# stm32h747i-disco dual quad with single NCS +#GPIO_BASE = 0x58020000; +#$Conf = "PG06:AF10:H, PB02:AF09:V, PF06:AF09:V, PF07:AF09:V, PF09:AF10:V, PD11:AF09:V, " +# . "PG14:AF09:H, PG09:AF09:V, PH03:AF09:V, PH02:AF09:V"; + +# stm32h7b3i-disco octal +#$GPIO_BASE = 0x58020000; +#$Conf = "PG06:AF10:V, PB02:AF09:V, PC05:AF10:V, PD07:AF10:V, PG09:AF09:V, PH03:AF09:V, PC01:AF10:V, " +# . "PF06:AF10:V, PF07:AF10:V, PF09:AF10:V, PD11:AF09:V"; + +# stm32h735g-disco octal +#$GPIO_BASE = 0x58020000; +#$Conf = "PG06:AF10:V, PF10:AF09:V, PB02:AF10:V, PD07:AF10:V, PG09:AF09:V, PD05:AF10:V, PD04:AF10:V, " +# . "PD13:AF09:V, PE02:AF09:V, PD12:AF09:V, PD11:AF09:V"; + +# stm32l562e-disco octal +#$GPIO_BASE = 0x42020000; +#$Conf = "PA02:AF10:V, PA03:AF10:V, PB02:AF10:V, PC00:AF03:V, PC03:AF10:V, PC02:AF10:V, PC01:AF10:V, " +# . "PA06:AF10:V, PA07:AF10:V, PB00:AF10:V, PB01:AF10:V"; + +&getopts('b:c:f:t'); +if ($Getopt::Std::opt_b eq '') +{ + if ($GPIO_BASE eq '') + { + die("usage: $0 [ -1 ] -b io_base [ -c port_configuration ] [ -f conf_file ]"); + } +} +else +{ + $GPIO_BASE = eval $Getopt::Std::opt_b; +} + +if ($Getopt::Std::opt_c eq '') +{ + if (($Conf eq '') && ($Getopt::Std::opt_f eq '')) + { + die("usage: $0 [ -b io_base ] ( -c port_configuration | -f conf_file )"); + } +}# +else +{ + $Conf = $Getopt::Std::opt_c . ','; +} + +$STM32F1 = $Getopt::Std::opt_t; + +my $Sep = "\t"; +my $Form = "${Sep}mmw 0x%08X 0x%08X 0x%08X\t;# "; + +my $GPIO_OFFS; +my $GPIO_CRL; +my $GPIO_CRH; +my $GPIO_MODER; +my $GPIO_OTYPER; +my $GPIO_OSPEEDR; +my $GPIO_PUPDR; +my $GPIO_IDR; +my $GPIO_ODR; +my $GPIO_AFRL; +my $GPIO_AFRH; + +if ($STM32F1) +{ + # offsets for F1 devices + $GPIO_OFFS = 0x400; + $GPIO_CRL = 0x00; + $GPIO_CRH = 0x04; + $GPIO_IDR = 0x08; + $GPIO_ODR = 0x0C; +} +else +{ + # these offsets are identical on all F0, F4, F7, H7, L4, L4+ devices up to now + $GPIO_OFFS = 0x400; + $GPIO_MODER = 0x00; + $GPIO_OTYPER = 0x04; + $GPIO_OSPEEDR = 0x08; + $GPIO_PUPDR = 0x0C; + $GPIO_IDR = 0x10; + $GPIO_ODR = 0x14; + $GPIO_AFRL = 0x20; + $GPIO_AFRH = 0x24; +} + +my @Out = ( { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { } ); +my @Port = ( ); +my $Exor; +my %Conf; +my $Pins = "${Sep}#"; + +my $pins; +my $altn; +my %defs; + +if ($Getopt::Std::opt_f ne '') +{ + open(CONF_FILE, '<', $Getopt::Std::opt_f) || die("can't open $Getopt::Std::opt_f"); + while (my $line = <CONF_FILE>) + { + if ($line =~ /^\s*#define\s+.?(QSPI|QUAD_?SPI|OCTOSPI[^_]*)\w+_(Port|Pin)\s/) + { + if ($line =~ /#define\s+(\w+)\s+(\w+)/) + { + $defs{$1} = $2; + } + else + { + die($line); + } + } + elsif ($line =~ /^\s*(P[A-Z])([0-9]+)\s*-+>\s+.?(QSPI|QUAD_?SPI|OCTO_?SPI[^_]*)_(\w+)/) + { + $Conf{$4} = sprintf("%s%02d", $1, $2); + } + elsif ($line =~ /^\s*GPIO_InitStruct.Pin\s*=\s*([^;]+\w)/) + { + $pins = $1; + while ($line !~ /;/) + { + $line = <CONF_FILE>; + $line =~ /^\s*([^;]+\w)/; + $pins .= $1; + } + } + elsif ($line =~ /^\s*GPIO_InitStruct.Alternate\s*=\s*GPIO_AF([0-9]+)/) + { + $altn = $1; + } + elsif ($line =~ /^\s*HAL_GPIO_Init\s*\(\s*(\w+)\s*,/) + { + my $port = $1; + if ($port =~ /GPIO([A-Z])/) + { + $port = $1; + } + elsif (exists($defs{$port})) + { + $defs{$port} =~ /GPIO([A-Z])/; + $port = $1; + } + else + { + printf("\n"); + next; + } + my @pin = split(/\s*\|\s*/, $pins); + foreach my $pin (@pin) + { + my $bit; + if (exists($defs{$pin})) + { + $defs{$pin} =~ /GPIO_PIN_([0-9]+)/; + $bit = $1; + } + else + { + $pin =~ /GPIO_PIN_([0-9]+)/; + $bit = $1; + } + $Conf .= sprintf("P%s%02d:AF%02d:V, ", $port, $bit, $altn); + } + $pins = ''; + $altn = 0; + } + } + close(CONF_FILE); +} +else +{ + my @names = ( ); + my @conf = split(/\s*,\s*/, $Conf); + + if (@conf == 2) + { + push(@names, 'SDA', 'SCL'); + } else { + if (@conf == 3) + { + push(@names, 'NCS', 'CLK', 'IO0/DIO'); + } + elsif (@conf == 4) + { + push(@names, 'NCS', 'CLK','IO1/MISO', 'IO0/MOSI'); + } + elsif (@conf == 6) + { + push(@names, 'NCS', 'CLK', 'IO3/NHOLD', 'IO2/NWP', 'IO1/MISO', 'IO0/MOSI'); + } + elsif (@conf == 10) + { + push(@names, 'NCS', 'CLK', 'BK_1_IO3/NHOLD', 'BK1_IO2/NWP', 'BK1_IO1/MISO', 'BK1_IO0/MOSI'); + push(@names, 'BK_2_IO3/NHOLD', 'BK2_IO2/NWP', 'BK2_IO1/MISO', 'BK2_IO0/MOSI'); + } + elsif (@conf == 11) + { + push(@names, 'BK_1_NCS', 'CLK', 'BK_1_IO3/NHOLD', 'BK1_IO2/NWP', 'BK1_IO1/MISO', 'BK1_IO0/MOSI'); + push(@names, 'BK_2_NCS', 'BK_2_IO3/NHOLD', 'BK2_IO2/NWP', 'BK2_IO1/MISO', 'BK2_IO0/MOSI'); + } + else + { + die("invalid config"); + } + } + + for (my $index = 0; $index < @conf; $index++) + { + uc($conf[$index]) =~ /^P([A-K])([0-9]+):\s*([A-Z0-9]+):(L|M|H|V)$/; + $Pins .= sprintf(" %s: P%s%02d,", $names[$index], $1, $2); + } + chop($Pins); +} + +if (exists $Conf{'BK1_IO0'}) +{ + # QuadSPI on F4, F7, H7 + my $line; + for my $i ('NCS', 'BK1_NCS', 'CLK', 'BK1_IO3', 'BK1_IO2', 'BK1_IO1', 'BK1_IO0') + { + (exists $Conf{$i}) && ($Pins .= sprintf(" %s: %s,", $Conf{$i}, $i)); + } +} + +if (exists $Conf{'BK2_IO0'}) +{ + # QuadSPI on F4, F7, H7 + my $line; + for my $i ('NCS', 'BK2_NCS', 'CLK', 'BK2_IO3', 'BK2_IO2', 'BK2_IO1', 'BK2_IO0') + { + (exists $Conf{$i}) && ($Pins .= sprintf(" %s: %s,", $Conf{$i}, $i)); + } +} + +if (exists $Conf{'P1_IO0'}) +{ + # OctoSPI on L4+, L5, H7 + my $line; + for my $i ('P1_NCS', 'P1_CLK', 'P1_DQS', 'P1_IO7', 'P1_IO6', 'P1_IO5', 'P1_IO4', + 'P1_IO3', 'P1_IO2', 'P1_IO1', 'P1_IO0') + { + (exists $Conf{$i}) && ($Pins .= sprintf(" %s: %s,", $Conf{$i}, $i)); + } +} + +if (exists $Conf{'P2_IO0'}) +{ + # OctoSPI on L4+, H7 + my $line; + for my $i ('P2_NCS', 'P2_CLK', 'P2_DQS', 'P2_IO7', 'P2_IO6', 'P2_IO5', 'P2_IO4', + 'P2_IO3', 'P2_IO2', 'P2_IO1', 'P2_IO0') + { + (exists $Conf{$i}) && ($Pins .= sprintf(" %s: %s,", $Conf{$i}, $i)); + } +} + +my @Col = ( ); +my @conf = split(/\s*,\s*/, $Conf); + +if (@conf == 3) +{ + splice(@conf, 2, 0, 'NONE', 'NONE', 'NONE'); +} +elsif (@conf == 4) +{ + splice(@conf, 2, 0, 'NONE', 'NONE'); +} + +foreach my $line (@conf) +{ + $line = uc($line); + $line =~ /^P([A-K])([0-9]+):\s*([A-Z0-9]+):(L|M|H|V)$/; + my $port = $1; + my $pin = $2; + my $conf = $3; + my $speed = $4; + + my $MODER = 0x0; + my $OTYPER = 0x0; + my $OSPEEDR = 0x0; + my $PUPDR = 0x0; + my $AFR = 0x0; + my $num = ord(${port}) - ord('A'); + my $out = $Out[$num]; + + (exists $$out{'DEF'}) || ($$out{'DEF'} = 0); + + if ($conf eq '') + { + if ($line ne 'NONE') + { + printf(STDERR "invalid conf %s\n", $line); + } + next; + } + elsif ($conf =~ /^AF([0-9]+)(|P|O)(|UP|DO)$/) + { + if ($STM32F1) + { + printf(STDERR "no alternate %s for F1 family\n", $line); + next; + } + if (($1 < 0) || ($1 > 15)) + { + printf(STDERR "invalid alternate %s\n", $line); + next; + } + $MODER = 0x2; + $AFR = $1; + if ($pin <= 7) + { + $$out{'AFRL_H'} |= ($AFR << (${pin} << 2)); + $$out{'AFRL_L'} |= (($AFR ^ 0xF) << (${pin} << 2)); + } + else + { + $$out{'AFRH_H'} |= ($AFR << ((${pin} - 8) << 2)); + $$out{'AFRH_L'} |= (($AFR ^ 0xF) << ((${pin} - 8) << 2)); + } + if ($2 ne '') { + $OTYPER = ($1 eq 'O') ? 0x1 : 0x0; + $$out{'OTYPER_H'} |= ($OTYPER << $pin); + $$out{'OTYPER_L'} |= (($OTYPER ^ 0x1) << $pin); + } + $PUPDR = ($3 eq 'UP') ? 0x1 : (($3 eq 'DO') ? 0x2 : 0x0); + $$out{'PUPDR_H'} |= ($PUPDR << (${pin} << 1)); + $$out{'PUPDR_L'} |= (($PUPDR ^0x3) << (${pin} << 1)); + $conf = sprintf("AF%02d%s%s", $AFR, $2, $3); + } + elsif ($conf =~ /^IN(|P|O)(|UP|DO)$/) + { + if ($STM32F1) + { + $MODER = ($1 eq '') ? 0x4 : 0x8; + ($2 eq 'UP') && ($$out{'PUPDR_H'} |= (1 << ${pin})); + ($2 eq 'DO') && ($$out{'PUPDR_L'} |= (1 << ${pin})); + } + else + { + $MODER = 0x0; + if ($1 ne '') + { + $OTYPER = ($1 eq 'O') ? 0x1 : 0x0; + $$out{'OTYPER_H'} |= ($OTYPER << $pin); + $$out{'OTYPER_L'} |= (($OTYPER ^ 0x1) << $pin); + } + $PUPDR = ($2 eq 'UP') ? 0x1 : (($2 eq 'DO') ? 0x2 : 0x0); + $$out{'PUPDR_H'} |= ($PUPDR << (${pin} << 1)); + $$out{'PUPDR_L'} |= (($PUPDR ^0x3) << (${pin} << 1)); + } + ($2 eq 'UP') && ($$out{'ODR_H'} |= (1 << ${pin})); + ($2 eq 'DO') && ($$out{'ODR_L'} |= (1 << ${pin})); + } + elsif ($conf =~ /^P(P|O)(|UP|DO)$/) + { + if ($STM32F1) + { + $MODER = ($1 eq 'O') ? 0x4 : 0x0; + $MODER |= (($speed eq 'V') ? 0x03 : (($speed eq 'L') ? 0x2 : 0x1)); + if ($2 ne '') + { + printf(STDERR "WARNING: no output w/ pull-up/pull-down for F1 family %s\n", $line); + } + } + else + { + $MODER = 0x1; + $OTYPER = ($1 eq 'O') ? 0x1 : 0x0; + $$out{'OTYPER_H'} |= ($OTYPER << $pin); + $$out{'OTYPER_L'} |= (($OTYPER ^ 0x1) << $pin); + $PUPDR = ($2 eq 'UP') ? 0x1 : (($2 eq 'DO') ? 0x2 : 0x0); + $$out{'PUPDR_H'} |= ($PUPDR << ($pin << 1)); + $$out{'PUPDR_L'} |= (($PUPDR ^ 0x3) << ($pin << 1)); + } + ($2 eq 'UP') && ($$out{'ODR_H'} |= (1 << ${pin})); + ($2 eq 'DO') && ($$out{'ODR_L'} |= (1 << ${pin})); + } + else + { + printf(STDERR "invalid conf %s\n", $line); + next; + } + + if ($$out{'DEF'} & (1<< ${pin})) + { + printf(STDERR "redefinition: %s\n", $line); + } + + if ($STM32F1) + { + if ($pin >= 8) + { + $$out{'CRH_H'} |= ($MODER << (($pin & 0x7) << 2)); + $$out{'CRH_L'} |= (($MODER ^ 0xF) << (($pin & 0x7) << 2)); + } + else + { + $$out{'CRL_H'} |= ($MODER << (($pin & 0x7) << 2)); + $$out{'CRL_L'} |= (($MODER ^ 0xF) << (($pin & 0x7) << 2)); + } + + $Exor = sprintf("0x%08X %2d", ${GPIO_BASE} + (ord($port) - ord('A')) * ${GPIO_OFFS} + ${GPIO_ODR}, $pin); + my $exor = 0xB << (($pin & 0x7) << 2); + (($MODER & 0x3) == 0x0) && ($Exor .= sprintf(" 0x%03X 0x%03X 0x%08X", + ((($pin >= 8) ? ${GPIO_CRH} : ${GPIO_CRL})-${GPIO_ODR}) & 0x3FF, + ((($pin >= 8) ? ${GPIO_CRH} : ${GPIO_CRL})-${GPIO_ODR}) & 0x3FF, $exor)); + } + else + { + $$out{'DEF'} |= (1 << ${pin}); + $$out{'MODER_H'} |= ($MODER << (${pin} << 1)); + $$out{'MODER_L'} |= (($MODER ^ 0x3) << (${pin} << 1)); + + $OSPEEDR = (($speed eq 'V') ? 0x3 : (($speed eq 'H') ? 0x2 : (($speed eq 'M') ? 0x1 : 0x0))); + $$out{'OSPEEDR_H'} |= ($OSPEEDR << (${pin} << 1)); + $$out{'OSPEEDR_L'} |= (($OSPEEDR ^ 0x3) << (${pin} << 1)); + + $Exor = sprintf("0x%08X %2d", ${GPIO_BASE} + (ord($port) - ord('A')) * ${GPIO_OFFS} + ${GPIO_ODR}, $pin); + my $exor = (0x1 << ($pin << 1)); + ($MODER == 0x0) && ($Exor .= sprintf(" 0x%03X 0x%03X 0x%08X", (${GPIO_MODER}-${GPIO_ODR}) & 0x3FF, + (${GPIO_MODER}-${GPIO_ODR}) & 0x3FF, $exor)); + } + + push(@{$Port[$num]}, sprintf("P%s%02d:%s:%s", $port, $pin, $conf, $speed)); + push(@Col, $Exor); +} + +my $Col = sprintf("${Sep}0x%03X ", (${GPIO_IDR}-${GPIO_ODR}) & 0x3FF); +for (my $i = 0; $i < @Col; $i++) +{ + if (($i != 0) && (($i % 2) == 0)) + { + (($i + 1) < @Col) && ($Col .= "\\\n${Sep}"); + } + $Col .= sprintf("%s ", $Col[$i]); +} +printf("%s\n", $Col); + +my @Col = ( ); +my $Set; +for (my $i = 0; $i < @Out; $i++) +{ + my $out = $Out[$i]; + my $addr = ${GPIO_BASE} + $i * ${GPIO_OFFS}; + my $count = 0; + + if ($STM32F1) + { + if (($$out{'CRH_H'} | $$out{'CRH_L'} | $$out{'CRL_H'} | $$out{'CRL_L'} | + $$out{'PUPDR_H'} | $$out{'PUPDR_L'}) != 0) + { + push(@Col, sort({ $b cmp $a } @{$Port[$i]})); + + $Set .= sprintf("\n%s# Port %s: %s\n", ${Sep}, chr($i + ord('A')), + join(", ", sort({ $b cmp $a } @{$Port[$i]}))); + + (($$out{'CRL_H'} | $$out{'CRL_L'}) != 0) && + ($Set .= sprintf("${Form}CRL\n", $addr + ${GPIO_CRL}, $$out{'CRL_H'}, $$out{'CRL_L'})); + + (($$out{'CRH_H'} | $$out{'CRH_L'}) != 0) && + ($Set .= sprintf("${Form}CRH\n", $addr + ${GPIO_CRH}, $$out{'CRH_H'}, $$out{'CRH_L'})); + + (($$out{'ODR_H'} | $$out{'ODR_L'}) != 0) && + ($Set .= sprintf("${Form}ODR/PUPDR\n", $addr + ${GPIO_ODR}, $$out{'ODR_H'}, $$out{'ODR_L'})); + } + } + else + { + if (($$out{'MODER_H'} | $$out{'MODER_L'} | + $$out{'OTYPER_H'} | $$out{'OTYPER_L'} | + $$out{'OSPEEDR_H'} | $$out{'OSPEEDR_L'} | + $$out{'PUPDR_H'} | $$out{'PUPDR_L'} | + $$out{'ODR_H'} | $$out{'ODR_L'} | + $$out{'AFRL_H'} | $$out{'AFRL_L'} | + $$out{'AFRH_H'} | $$out{'AFRH_L'}) != 0) + { + push(@Col, sort({ $b cmp $a } @{$Port[$i]})); + + $Set .= sprintf("%s# Port %s: %s\n", ${Sep}, chr($i + ord('A')), + join(", ", sort({ $b cmp $a } @{$Port[$i]}))); + + (($$out{'MODER_H'} | $$out{'MODER_L'}) != 0) && + ($Set .= sprintf("${Form}MODER\n", $addr + ${GPIO_MODER}, $$out{'MODER_H'}, $$out{'MODER_L'})); + + (($$out{'OTYPER_H'} | $$out{'OTYPER_L'}) != 0) && + ($Set .= sprintf("${Form}OTYPER\n", $addr + ${GPIO_OTYPER}, $$out{'OTYPER_H'}, $$out{'OTYPER_L'})); + + (($$out{'OSPEEDR_H'} | $$out{'OSPEEDR_L'}) != 0) && + ($Set .= sprintf("${Form}OSPEEDR\n", $addr + ${GPIO_OSPEEDR}, $$out{'OSPEEDR_H'}, $$out{'OSPEEDR_L'})); + + (($$out{'PUPDR_H'} | $$out{'PUPDR_L'}) != 0) && + ($Set .= sprintf("${Form}PUPDR\n", $addr + ${GPIO_PUPDR}, $$out{'PUPDR_H'}, $$out{'PUPDR_L'})); + + (($$out{'ODR_H'} | $$out{'ODR_L'}) != 0) && + ($Set .= sprintf("${Form}ODR\n", $addr + ${GPIO_ODR}, $$out{'ODR_H'}, $$out{'ODR_L'})); + + (($$out{'AFRL_H'} | $$out{'AFRL_L'}) != 0) && + ($Set .= sprintf("${Form}AFRL\n", $addr + ${GPIO_AFRL}, $$out{'AFRL_H'}, $$out{'AFRL_L'})); + + (($$out{'AFRH_H'} | $$out{'AFRH_L'}) != 0) && + ($Set .= sprintf("${Form}AFRH\n", $addr + ${GPIO_AFRH}, $$out{'AFRH_H'}, $$out{'AFRH_L'})); + } + } +} + +my $Col = ''; +for (my $i = 0; $i < @Col; $i++) +{ + if (($i % 6) == 0) + { + chop($Col); + (($i + 1) < @Col) && ($Col .= "\n${Sep}#"); + } + $Col .= sprintf(" %s,", $Col[$i]); +} +chop($Col); +#printf("\n%s\n", $Pins); +printf("%s\n", $Col); +printf("%s\n", $Set); diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_crc32.S b/contrib/loaders/flash/stmqspi/stmoctospi_crc32.S new file mode 100644 index 000000000..941ea42c6 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_crc32.S @@ -0,0 +1,123 @@ +/*************************************************************************** + * Copyright (C) 2019 by Andreas Bolsch * + * and...@mn... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + .thumb_func + +/* Params: + * r0 - total count (bytes), crc32 (out) + * r1 - flash page size + * r2 - address offset into flash + * r3 - OCTOSPI io_base + + * Clobbered: + * r4 - tmp + * r5 - address of OCTOSPI_DR + * r6 - address of OCTOSPI_CCR + * r7 - tmp + */ + +#include "../../../../src/flash/nor/stmqspi.h" + +#define OCTOSPI_CCR_CCR (OCTOSPI_CCR - OCTOSPI_CCR) +#define OCTOSPI_TCR_CCR (OCTOSPI_TCR - OCTOSPI_CCR) +#define OCTOSPI_IR_CCR (OCTOSPI_IR - OCTOSPI_CCR) + + .macro octospi_abort + movs r5, #(1<<SPI_ABORT) /* abort bit mask */ + ldr r7, [r3, #OCTOSPI_CR] /* get OCTOSPI CR register */ + orrs r7, r7, r5 /* set abort bit */ + str r7, [r3, #OCTOSPI_CR] /* store new CR register */ + .endm + + .macro wait_busy +0: + ldr r7, [r3, #OCTOSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_BUSY+1) /* shift BUSY into C */ + bcs 0b /* loop until BUSY cleared */ + movs r7, #(1<<SPI_TCF) /* TCF bitmask */ + str r7, [r3, #OCTOSPI_FCR] /* clear TCF flag */ + .endm + +start: + subs r0, r0, #1 /* decrement count for DLR */ + subs r1, r1, #1 /* page size mask and for DLR */ + movs r4, #0x00 /* initialize crc */ + mvns r4, r4 /* to 0xFFFFFFFF */ +start_read: + octospi_abort /* start in clean state */ + movs r5, #OCTOSPI_DR /* load OCTOSPI_DR address offset */ + adds r5, r5, r3 /* address of OCTOSPI_DR */ + movs r6, #OCTOSPI_CCR-OCTOSPI_DR /* load OCTOSPI_CCR address offset */ + adds r6, r6, r5 /* address of OCTOSPI_CCR */ + wait_busy + ldr r7, cr_page_read /* indirect read mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + mov r7, r2 /* get current start address */ + orrs r7, r7, r1 /* end of current page */ + subs r7, r7, r2 /* count-1 to end of page */ + cmp r7, r0 /* if this count <= remaining */ + bls write_dlr /* then read to end of page */ + mov r7, r0 /* else read all remaining */ +write_dlr: + str r7, [r3, #OCTOSPI_DLR] /* size-1 in DLR register */ + ldr r7, ccr_page_read /* CCR for read */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate transfer */ + ldr r7, tcr_page_read /* TCR for read */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_page_read /* IR for read */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + str r2, [r3, #OCTOSPI_AR] /* store SPI start address */ + ldr r6, =0x04C11DB7 /* CRC32 polynomial */ +read_loop: + ldrb r7, [r5] /* read next byte from DR */ + lsls r7, r7, #24 /* shift into msb */ + eors r4, r4, r7 + .rept 8 /* unrolled bit loop */ + asrs r7, r4, #31 /* copy bit 31 into bits 0 to 31 */ + ands r7, r7, r6 /* r7 neg. -> CRC32XOR, pos. -> 0x0 */ + lsls r4, r4, #1 /* shift result */ + eors r4, r4, r7 /* eor by CRC32XOR or 0x0 */ + .endr + adds r2, r2, #1 /* increment address */ + subs r0, r0, #1 /* decrement (count-1) */ + bmi exit /* stop if no data left */ + tst r2, r1 /* page end ? */ + bne read_loop /* if not, then next byte */ +page_end: + bal start_read /* then next page */ + .pool + +exit: + mvns r0, r4 /* invert to get final result */ + octospi_abort /* to idle state */ + .align 2 /* align to word, bkpt is 4 words */ + bkpt #0 /* before code end for exit_point */ + .align 2 /* align to word */ + +cr_page_read: + .space 4 /* OCTOSPI_CR value for read command */ +ccr_page_read: + .space 4 /* OCTOSPI_CCR value for read command */ +tcr_page_read: + .space 4 /* OCTOSPI_TCR value for read command */ +ir_page_read: + .space 4 /* OCTOSPI_IR value for read command */ diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_crc32.inc b/contrib/loaders/flash/stmqspi/stmoctospi_crc32.inc new file mode 100644 index 000000000..afc616883 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_crc32.inc @@ -0,0 +1,13 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x01,0x38,0x01,0x39,0x00,0x24,0xe4,0x43,0x02,0x25,0x1f,0x68,0x2f,0x43,0x1f,0x60, +0x50,0x25,0xed,0x18,0xb0,0x26,0x76,0x19,0x1f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27, +0x5f,0x62,0x22,0x4f,0x1f,0x60,0x17,0x46,0x0f,0x43,0xbf,0x1a,0x87,0x42,0x00,0xd9, +0x07,0x46,0x1f,0x64,0x1e,0x4f,0x37,0x60,0x1e,0x4f,0xb7,0x60,0x1e,0x4f,0x37,0x61, +0x9a,0x64,0x15,0x4e,0x2f,0x78,0x3f,0x06,0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00, +0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00,0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00, +0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00,0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00, +0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00,0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00, +0x7c,0x40,0xe7,0x17,0x37,0x40,0x64,0x00,0x7c,0x40,0x01,0x32,0x01,0x38,0x05,0xd4, +0x0a,0x42,0xd7,0xd1,0xb8,0xe7,0x00,0x00,0xb7,0x1d,0xc1,0x04,0xe0,0x43,0x02,0x25, +0x1f,0x68,0x2f,0x43,0x1f,0x60,0xc0,0x46,0x00,0xbe,0xc0,0x46,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.S b/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.S new file mode 100644 index 000000000..3af82d4d8 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.S @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2019 by Andreas Bolsch * + * and...@mn... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + .thumb_func + +/* Params: + * r0 - sector count + * r1 - QSPI io_base + + * Clobbered: + * r2 - r7 tmp */ + +#include "../../../../src/flash/nor/stmqspi.h" + +#define OCTOSPI_CCR_CCR (OCTOSPI_CCR - OCTOSPI_CCR) +#define OCTOSPI_TCR_CCR (OCTOSPI_TCR - OCTOSPI_CCR) +#define OCTOSPI_IR_CCR (OCTOSPI_IR - OCTOSPI_CCR) + + .macro octospi_abort + movs r5, #(1<<SPI_ABORT) /* abort bit mask */ + ldr r7, [r1, #OCTOSPI_CR] /* get OCTOSPI_CR register */ + orrs r7, r7, r5 /* set abort bit */ + str r7, [r1, #OCTOSPI_CR] /* store new CR register */ + .endm + + .macro wait_busy +0: + ldr r7, [r1, #OCTOSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_BUSY+1) /* shift BUSY into C */ + bcs 0b /* loop until BUSY cleared */ + movs r7, #(1<<SPI_TCF) /* TCF bitmask */ + str r7, [r1, #OCTOSPI_FCR] /* clear TCF flag */ + .endm + +start: + adr r2, buffer /* pointer to start of buffer */ + movs r3, #OCTOSPI_DR /* load OCTOSPI_DR address offset */ + adds r3, r3, r1 /* address of OCTOSPI_DR */ +sector_start: + octospi_abort /* start in clean state */ + movs r6, #OCTOSPI_CCR-OCTOSPI_DR /* load OCTOSPI_CCR address offset */ + adds r6, r6, r3 /* address of OCTOSPI_CCR */ + wait_busy + ldr r7, cr_page_read /* indirect read mode */ + str r7, [r1, #OCTOSPI_CR] /* set mode */ + ldmia r2!, {r4, r5} /* load address offset, length */ + subs r2, r2, #4 /* point to length */ + subs r5, r5, #1 /* decrement sector length for DLR */ + str r5, [r1, #OCTOSPI_DLR] /* size-1 in DLR register */ + ldr r7, ccr_page_read /* CCR for read */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate transfer */ + ldr r7, tcr_page_read /* TCR for read */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_page_read /* IR for read */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + str r4, [r1, #OCTOSPI_AR] /* store SPI start address */ + ldr r6, [r2, #4] /* load initial value */ +read_loop: + ldrb r4, [r3, #0] /* read next byte from DR */ + movs r7, #0xFF /* fill bits 8-15 */ + lsls r7, r7, #8 /* with ones */ + orrs r4, r4, r7 /* copy ones to left of read byte */ + ands r6, r6, r4 /* and read byte to result */ + lsls r4, r4, #8 /* shift result into higher byte */ + orrs r6, r6, r4 /* or read byte to result */ + subs r5, r5, #1 /* decrement byte (count-1) */ + bpl read_loop /* again if sector not completed */ + adds r5, r5, #1 /* increment count due to the -1 */ + stmia r2!, {r5, r6} /* save final count and result for sector */ + subs r0, r0, #1 /* decrement sector count */ + bne sector_start /* next sector? */ + octospi_abort /* to idle state */ + +exit: + .align 2 /* align to word, bkpt is 4 words */ + bkpt #0 /* before code end for exit_point */ + .align 2 /* align to word */ + +cr_page_read: + .space 4 /* OCTOSPI_CR value for read command */ +ccr_page_read: + .space 4 /* OCTOSPI_CCR value for read command */ +tcr_page_read: + .space 4 /* OCTOSPI_TCR value for read command */ +ir_page_read: + .space 4 /* OCTOSPI_IR value for read command */ + + .equ buffer, . + diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.inc b/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.inc new file mode 100644 index 000000000..c0e124ac0 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_erase_check.inc @@ -0,0 +1,8 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x1b,0xa2,0x50,0x23,0x5b,0x18,0x02,0x25,0x0f,0x68,0x2f,0x43,0x0f,0x60,0xb0,0x26, +0xf6,0x18,0x0f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27,0x4f,0x62,0x10,0x4f,0x0f,0x60, +0x30,0xca,0x04,0x3a,0x01,0x3d,0x0d,0x64,0x0e,0x4f,0x37,0x60,0x0e,0x4f,0xb7,0x60, +0x0e,0x4f,0x37,0x61,0x8c,0x64,0x56,0x68,0x1c,0x78,0xff,0x27,0x3f,0x02,0x3c,0x43, +0x26,0x40,0x24,0x02,0x26,0x43,0x01,0x3d,0xf6,0xd5,0x01,0x35,0x60,0xc2,0x01,0x38, +0xd9,0xd1,0x02,0x25,0x0f,0x68,0x2f,0x43,0x0f,0x60,0xc0,0x46,0x00,0xbe,0xc0,0x46, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_read.S b/contrib/loaders/flash/stmqspi/stmoctospi_read.S new file mode 100644 index 000000000..fb5ff1ff9 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_read.S @@ -0,0 +1,142 @@ +/*************************************************************************** + * Copyright (C) 2019 by Andreas Bolsch * + * and...@mn... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + .thumb_func + +/* Params: + * r0 - total count (bytes), remaining bytes (out, 0 means successful) + * r1 - flash page size + * r2 - address offset into flash + * r3 - OCTOSPI io_base + * r8 - fifo start + * r9 - fifo end + 1 + + * Clobbered: + * r4 - wp + * r5 - address of OCTOSPI_DR + * r6 - address of OCTOSPI_CCR + * r7 - tmp + */ + +#include "../../../../src/flash/nor/stmqspi.h" + +#define OCTOSPI_CCR_CCR (OCTOSPI_CCR - OCTOSPI_CCR) +#define OCTOSPI_TCR_CCR (OCTOSPI_TCR - OCTOSPI_CCR) +#define OCTOSPI_IR_CCR (OCTOSPI_IR - OCTOSPI_CCR) + + .macro octospi_abort + movs r5, #(1<<SPI_ABORT) /* abort bit mask */ + ldr r7, [r3, #OCTOSPI_CR] /* get OCTOSPI CR register */ + orrs r7, r7, r5 /* set abort bit */ + str r7, [r3, #OCTOSPI_CR] /* store new CR register */ + .endm + + .macro wait_busy +0: + ldr r7, [r3, #OCTOSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_BUSY+1) /* shift BUSY into C */ + bcs 0b /* loop until BUSY cleared */ + movs r7, #(1<<SPI_TCF) /* TCF bitmask */ + str r7, [r3, #OCTOSPI_FCR] /* clear TCF flag */ + .endm + +start: + subs r0, r0, #1 /* decrement count for DLR */ + subs r1, r1, #1 /* page size mask and for DLR */ + ldr r4, wp /* load wp */ +start_read: + octospi_abort /* start in clean state */ + movs r5, #OCTOSPI_DR /* load OCTOSPI_DR address offset */ + adds r5, r5, r3 /* address of OCTOSPI_DR */ + movs r6, #OCTOSPI_CCR-OCTOSPI_DR /* load OCTOSPI_CCR address offset */ + adds r6, r6, r5 /* address of OCTOSPI_CCR */ + wait_busy + ldr r7, cr_page_read /* indirect read mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + mov r7, r2 /* get current start address */ + orrs r7, r7, r1 /* end of current page */ + subs r7, r7, r2 /* count-1 to end of page */ + cmp r7, r0 /* if this count <= remaining */ + bls write_dlr /* then write to end of page */ + mov r7, r0 /* else write all remaining */ +write_dlr: + str r7, [r3, #OCTOSPI_DLR] /* size-1 in DLR register */ + ldr r7, ccr_page_read /* CCR for read */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate transfer */ + ldr r7, tcr_page_read /* TCR for read */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_page_read /* IR for read */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + str r2, [r3, #OCTOSPI_AR] /* store SPI start address */ +read_loop: + ldrb r7, [r5] /* read next byte from DR */ + strb r7, [r4, #0] /* write next byte */ + adds r4, r4, #1 /* increment internal wp */ + cmp r4, r9 /* internal wp beyond end? */ + blo wait_fifo /* if no, then ok */ + mov r4, r8 /* else wrap around */ +wait_fifo: + ldr r7, rp /* get rp */ + cmp r7, #0 /* if rp equals 0 */ + beq exit /* then abort */ + cmp r4, r7 /* check if fifo full */ + beq wait_fifo /* wait until not full */ + adr r7, wp /* get address of wp */ + str r4, [r7] /* store updated wp */ + adds r2, r2, #1 /* increment address */ + subs r0, r0, #1 /* decrement (count-1) */ + bmi exit /* stop if no data left */ + tst r2, r1 /* page end ? */ + bne read_loop /* if not, then next byte */ +page_end: + bal start_read /* then next page */ + +exit: + adds r0, r0, #1 /* increment count due to the -1 */ + octospi_abort /* to idle state */ + + .align 2 /* align to word, bkpt is 4 words */ + bkpt #0 /* before code end for exit_point */ + .align 2 /* align to word */ + + .space 4 /* not used */ + .space 4 /* not used */ + .space 4 /* not used */ + .space 4 /* not used */ + + .space 4 /* not used */ + .space 4 /* not used */ + .space 4 /* not used */ + .space 4 /* not used */ + +cr_page_read: + .space 4 /* OCTOSPI_CR value for read command */ +ccr_page_read: + .space 4 /* OCTOSPI_CCR value for read command */ +tcr_page_read: + .space 4 /* OCTOSPI_TCR value for read command */ +ir_page_read: + .space 4 /* OCTOSPI_IR value for read command */ + + .equ wp, . /* wp, uint32_t */ + .equ rp, wp + 4 /* rp, uint32_t */ + .equ buffer, rp + 4 /* buffer follows right away */ diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_read.inc b/contrib/loaders/flash/stmqspi/stmoctospi_read.inc new file mode 100644 index 000000000..583f31666 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_read.inc @@ -0,0 +1,12 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x01,0x38,0x01,0x39,0x27,0x4c,0x02,0x25,0x1f,0x68,0x2f,0x43,0x1f,0x60,0x50,0x25, +0xed,0x18,0xb0,0x26,0x76,0x19,0x1f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27,0x5f,0x62, +0x1c,0x4f,0x1f,0x60,0x17,0x46,0x0f,0x43,0xbf,0x1a,0x87,0x42,0x00,0xd9,0x07,0x46, +0x1f,0x64,0x19,0x4f,0x37,0x60,0x19,0x4f,0xb7,0x60,0x19,0x4f,0x37,0x61,0x9a,0x64, +0x2f,0x78,0x27,0x70,0x01,0x34,0x4c,0x45,0x00,0xd3,0x44,0x46,0x16,0x4f,0x00,0x2f, +0x09,0xd0,0xbc,0x42,0xfa,0xd0,0x13,0xa7,0x3c,0x60,0x01,0x32,0x01,0x38,0x02,0xd4, +0x0a,0x42,0xed,0xd1,0xcf,0xe7,0x01,0x30,0x02,0x25,0x1f,0x68,0x2f,0x43,0x1f,0x60, +0x00,0xbe,0xc0,0x46,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_write.S b/contrib/loaders/flash/stmqspi/stmoctospi_write.S new file mode 100644 index 000000000..867a02483 --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_write.S @@ -0,0 +1,219 @@ +/*************************************************************************** + * Copyright (C) 2018 by Andreas Bolsch * + * and...@mn... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + .thumb_func + +/* Params: + * r0 - total count (bytes), remaining bytes (out, 0 means successful) + * r1 - flash page size + * r2 - address offset into flash + * r3 - OCTOSPI io_base + * r8 - fifo start + * r9 - fifo end + 1 + + * Clobbered: + * r4 - rp + * r5 - address of OCTOSPI_DR + * r6 - address of OCTOSPI_CCR + * r7 - tmp + * r10 - single 0x0 / dual 0x1 + */ + +#include "../../../../src/flash/nor/stmqspi.h" + +#define OCTOSPI_CCR_CCR (OCTOSPI_CCR - OCTOSPI_CCR) +#define OCTOSPI_TCR_CCR (OCTOSPI_TCR - OCTOSPI_CCR) +#define OCTOSPI_IR_CCR (OCTOSPI_IR - OCTOSPI_CCR) + + .macro octospi_abort + movs r5, #(1<<SPI_ABORT) /* abort bit mask */ + ldr r7, [r3, #OCTOSPI_CR] /* get OCTOSPI CR register */ + orrs r7, r7, r5 /* set abort bit */ + str r7, [r3, #OCTOSPI_CR] /* store new CR register */ + .endm + + .macro wait_busy +0: + ldr r7, [r3, #OCTOSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_BUSY+1) /* shift BUSY into C */ + bcs 0b /* loop until BUSY cleared */ + movs r7, #(1<<SPI_TCF) /* TCF bitmask */ + str r7, [r3, #OCTOSPI_FCR] /* clear TCF flag */ + .endm + +start: + subs r0, r0, #1 /* decrement count for DLR */ + subs r1, r1, #1 /* page size mask and for DLR */ + ldr r4, rp /* load rp */ + ldr r7, [r3, #OCTOSPI_CR] /* get OCTOSPI_CR register */ + lsls r7, r7, #(31-SPI_DUAL_FLASH) /* clear higher order bits */ + lsrs r7, r7, #31 /* DUAL_FLASH bit into bit 0 */ + mov r10, r7 /* save in r10 */ +wip_loop: + octospi_abort /* start in clean state */ + movs r5, #OCTOSPI_DR /* load OCTOSPI_DR address offset */ + adds r5, r5, r3 /* address of OCTOSPI_DR */ + movs r6, #OCTOSPI_CCR-OCTOSPI_DR /* load OCTOSPI_CCR address offset */ + adds r6, r6, r5 /* address of OCTOSPI_CCR */ + wait_busy + ldr r7, cr_read_status /* indirect read mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + mov r7, r10 /* get dual bit */ + str r7, [r3, #OCTOSPI_DLR] /* one or two (for dual) bytes */ + ldr r7, ccr_read_status /* CCR for status read */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate status read */ + ldr r7, tcr_read_status /* TCR for status read */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_read_status /* IR for status read */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + movs r7, #0 /* dummy address */ + str r7, [r3, #OCTOSPI_AR] /* into AR (for 8-line mode) */ + ldrb r7, [r5] /* get first status register */ + lsrs r7, r7, #(SPIFLASH_BSY+1) /* if first flash busy, */ + bcs wip_loop /* then poll again */ + mov r7, r10 /* get dual bit */ + tst r7, r7 /* dual mode ? */ + beq write_enable /* not dual, then ok */ + ldrb r7, [r5] /* get second status register */ + lsrs r7, r7, #(SPIFLASH_BSY+1) /* if second flash busy, */ + bcs wip_loop /* then poll again */ +write_enable: + tst r0, r0 /* test residual count */ + bmi exit /* if negative, then finished */ + wait_busy + ldr r7, cr_write_enable /* indirect write mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + ldr r7, ccr_write_enable /* CCR for write enable */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate write enable */ + ldr r7, tcr_write_enable /* TCR for write enable */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* write enable instruction */ + ldr r7, ir_write_enable /* IR for write enable */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + movs r7, #0 /* silicon bug in L5? dummy write */ + str r7, [r3, #OCTOSPI_AR] /* into AR resolves issue */ + wait_busy + ldr r7, cr_read_status /* indirect read mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + mov r7, r10 /* get dual count */ + str r7, [r3, #OCTOSPI_DLR] /* one or two (for dual) bytes */ + ldr r7, ccr_read_status /* CCR for status read */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate status read */ + ldr r7, tcr_read_status /* TCR for status read */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_read_status /* IR for status read */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + movs r7, #0 /* dummy address */ + str r7, [r3, #OCTOSPI_AR] /* into AR (for 8-line mode) */ + ldrb r7, [r5] /* get first status register */ + lsrs r7, r7, #(SPIFLASH_WE+1) /* if first flash not */ + bcc error /* write enabled, then error */ + mov r7, r10 /* get dual bit */ + tst r7, r7 /* dual mode ? */ + beq start_write /* not dual, then ok */ + ldrb r7, [r5] /* get second status register */ + lsrs r7, r7, #(SPIFLASH_WE+1) /* if second flash not */ + bcc error /* write enabled, then error */ +start_write: + wait_busy + ldr r7, cr_page_write /* indirect write mode */ + str r7, [r3, #OCTOSPI_CR] /* set mode */ + mov r7, r2 /* get current start address */ + orrs r7, r7, r1 /* end of current page */ + subs r7, r7, r2 /* count-1 to end of page */ + cmp r7, r0 /* if this count <= remaining */ + bls write_dlr /* then write to end of page */ + mov r7, r0 /* else write all remaining */ +write_dlr: + str r7, [r3, #OCTOSPI_DLR] /* size-1 in DLR register */ + ldr r7, ccr_page_write /* CCR for page write */ + str r7, [r6, #OCTOSPI_CCR_CCR] /* initiate transfer */ + ldr r7, tcr_page_write /* TCR for page write */ + str r7, [r6, #OCTOSPI_TCR_CCR] /* instruction */ + ldr r7, ir_page_write /* IR for page write */ + str r7, [r6, #OCTOSPI_IR_CCR] /* instruction */ + str r2, [r3, #OCTOSPI_AR] /* store SPI start address */ +write_loop: + ldr r7, wp /* get wp */ + cmp r7, #0 /* if wp equals 0 */ + beq exit /* then abort */ + cmp r4, r7 /* check if fifo empty */ + beq write_loop /* wait until not empty */ + ldrb r7, [r4, #0] /* read next byte */ + strb r7, [r5] /* write next byte to DR */ + adds r4, r4, #1 /* increment internal rp */ + cmp r4, r9 /* internal rp beyond end? */ + blo upd_write /* if no, then ok */ + mov r4, r8 /* else wrap around */ +upd_write: + adr r7, rp /* get address of rp */ + str r4, [r7] /* store updated rp */ + adds r2, r2, #1 /* increment address */ + subs r0, r0, #1 /* decrement (count-1) */ + bmi page_end /* stop if no data left */ + tst r2, r1 /* page end ? */ + bne write_loop /* if not, then next byte */ +page_end: + ldr r7, [r3, #OCTOSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_TCF+1) /* shift TCF into C */ + bcc page_end /* loop until TCF set */ + bal wip_loop /* then next page */ + +error: + movs r0, #0 /* return 0xFFFFFFFF */ + subs r0, r0, #2 /* for error */ +exit: + adds r0, r0, #1 /* increment count due to the -1 */ + octospi_abort /* to idle state */ + .align 2 /* align to word, bkpt is 4 words */ + bkpt #0 /* before code end for exit_point */ + .align 2 /* align to word */ + +cr_read_status: + .space 4 /* OCTOSPI_CR value for READ_STATUS command */ +ccr_read_status: + .space 4 /* OCTOSPI_CCR value for READ_STATUS command */ +tcr_read_status: + .space 4 /* OCTOSPI_TCR value for READ_STATUS command */ +ir_read_status: + .space 4 /* OCTOSPI_IR value for READ_STATUS command */ + +cr_write_enable: + .space 4 /* OCTOSPI_CR value for WRITE_ENABLE command */ +ccr_write_enable: + .space 4 /* OCTOSPI_CCR value for WRITE_ENABLE command */ +tcr_write_enable: + .space 4 /* OCTOSPI_TCR value for WRITE_ENABLE command */ +ir_write_enable: + .space 4 /* OCTOSPI_IR value for WRITE_ENABLE command */ + +cr_page_write: + .space 4 /* OCTOSPI_CR value for PAGE_PROG command */ +ccr_page_write: + .space 4 /* OCTOSPI_CCR value for PAGE_PROG command */ +tcr_page_write: + .space 4 /* OCTOSPI_TCR value for PAGE_PROG command */ +ir_page_write: + .space 4 /* OCTOSPI_IR value for PAGE_PROG command */ + + .equ wp, . /* wp, uint32_t */ + .equ rp, wp + 4 /* rp, uint32_t */ + .equ buffer, rp + 4 /* buffer follows right away */ diff --git a/contrib/loaders/flash/stmqspi/stmoctospi_write.inc b/contrib/loaders/flash/stmqspi/stmoctospi_write.inc new file mode 100644 index 000000000..81781a2ca --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmoctospi_write.inc @@ -0,0 +1,21 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x01,0x38,0x01,0x39,0x4f,0x4c,0x1f,0x68,0x7f,0x06,0xff,0x0f,0xba,0x46,0x02,0x25, +0x1f,0x68,0x2f,0x43,0x1f,0x60,0x50,0x25,0xed,0x18,0xb0,0x26,0x76,0x19,0x1f,0x6a, +0xbf,0x09,0xfc,0xd2,0x02,0x27,0x5f,0x62,0x39,0x4f,0x1f,0x60,0x57,0x46,0x1f,0x64, +0x38,0x4f,0x37,0x60,0x38,0x4f,0xb7,0x60,0x38,0x4f,0x37,0x61,0x00,0x27,0x9f,0x64, +0x2f,0x78,0x7f,0x08,0xe3,0xd2,0x57,0x46,0x3f,0x42,0x02,0xd0,0x2f,0x78,0x7f,0x08, +0xdd,0xd2,0x00,0x42,0x55,0xd4,0x1f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27,0x5f,0x62, +0x2f,0x4f,0x1f,0x60,0x2f,0x4f,0x37,0x60,0x2f,0x4f,0xb7,0x60,0x2f,0x4f,0x37,0x61, +0x00,0x27,0x9f,0x64,0x1f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27,0x5f,0x62,0x24,0x4f, +0x1f,0x60,0x57,0x46,0x1f,0x64,0x23,0x4f,0x37,0x60,0x23,0x4f,0xb7,0x60,0x23,0x4f, +0x37,0x61,0x00,0x27,0x9f,0x64,0x2f,0x78,0xbf,0x08,0x30,0xd3,0x57,0x46,0x3f,0x42, +0x02,0xd0,0x2f,0x78,0xbf,0x08,0x2a,0xd3,0x1f,0x6a,0xbf,0x09,0xfc,0xd2,0x02,0x27, +0x5f,0x62,0x1f,0x4f,0x1f,0x60,0x17,0x46,0x0f,0x43,0xbf,0x1a,0x87,0x42,0x00,0xd9, +0x07,0x46,0x1f,0x64,0x1b,0x4f,0x37,0x60,0x1b,0x4f,0xb7,0x60,0x1b,0x4f,0x37,0x61, +0x9a,0x64,0x1b,0x4f,0x00,0x2f,0x14,0xd0,0xbc,0x42,0xfa,0xd0,0x27,0x78,0x2f,0x70, +0x01,0x34,0x4c,0x45,0x00,0xd3,0x44,0x46,0x16,0xa7,0x3c,0x60,0x01,0x32,0x01,0x38, +0x01,0xd4,0x0a,0x42,0xed,0xd1,0x1f,0x6a,0xbf,0x08,0xfc,0xd3,0x87,0xe7,0x00,0x20, +0x02,0x38,0x01,0x30,0x02,0x25,0x1f,0x68,0x2f,0x43,0x1f,0x60,0x00,0xbe,0xc0,0x46, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/stmqspi/stmqspi_crc32.S b/contrib/loaders/flash/stmqspi/stmqspi_crc32.S new file mode 100644 index 000000000..bfb2662ca --- /dev/null +++ b/contrib/loaders/flash/stmqspi/stmqspi_crc32.S @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2019 by Andreas Bolsch * + * and...@mn... * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + .text + .syntax unified + .cpu cortex-m0 + .thumb + .thumb_func + +/* Params: + * r0 - total count (bytes), crc32 (out) + * r1 - flash page size + * r2 - address offset into flash + * r3 - QSPI io_base + + * Clobbered: + * r4 - rp + * r5 - address of QSPI_DR + * r7 - tmp + */ + +#include "../../../../src/flash/nor/stmqspi.h" + + .macro qspi_abort + movs r5, #(1<<SPI_ABORT) /* abort bit mask */ + ldr r7, [r3, #QSPI_CR] /* get QSPI_CR register */ + orrs r7, r7, r5 /* set abort bit */ + str r7, [r3, #QSPI_CR] /* store new CR register */ + .endm + + .macro wait_busy +0: + ldr r7, [r3, #QSPI_SR] /* load status */ + lsrs r7, r7, #(SPI_BUSY+1) /* shift BUSY into C */ + bcs 0b /* loop until BUSY cleared */ + movs r7, #(1<<SPI_TCF) /* TCF bitmask */ + str r7, [r3, #QSPI_FCR] /* clear TCF flag */ + .endm + +start: + subs r0, r0, #1 /* decrement count for DLR */ + subs r1, r1, #1 /* page size mask and for DLR */ + movs r4, #0x00 /* initialize crc */ + mvns r4, r4 /* to 0xFFFFFFFF */ +start_read: + qspi_abort /* start in clean state */ + movs r5, #QSPI_DR /* load QSPI_DR address offset */ + adds r5, r5, r3 /* address of QSPI_DR */ + wait_busy + mov r7, r2 /* get current start address */ + orrs r7, r7, r1 /* end of current page */ + subs r7, r7, r2 /* count-1 to end of page */ + cmp r7, r0 /* if this count <= remaining */ + bls write_dlr /* then read to end of page */ + mov r7, r0 /* else read all remaining */ +write_dlr: + str r7, [r3, #QSPI_DLR] /* size-1 in DLR register */ + ldr r7, ccr_page_read /* CCR for page read */ + str r7, [r3, #QSPI_CCR] /* initiate transfer */ + str r2, [r3, #QSPI_AR] /* store SPI start address */ + ldr r7, [r3, #QSPI_SR] /* wait for command startup */ + ldr r6, =0x04C11DB7 /* CRC32 polynomial */ +read_loop: + ldrb r7, [r5] /* read next byte from DR */ + lsls r7, r7, #24 /* shift into msb */ + eors r4, r4, r7 + .rept 8 /* unrolled bit loop */ + asrs r7, r4, #31 /* copy bit 31 into bits 0 to 31 */ + ands r7, r7, r6 /* r7 neg. -> CRC32XOR, pos. -> 0x0 */ + lsls r4, r4, #1 /* shift result */ + eors r4, r4, r7 /* eor by CRC32XOR or 0x0 */ + .endr + adds r2, r2, #1 /* increment address */ + subs r0, r0, #1 /* decrement (count-1) */ + bmi exit /* stop if no data left */ + tst r2, r1 /* page end ? */ + bne read_loop /* if not, then next byte */ +page_end: + bal start_read /* then next page */ + .pool + +exit: + mvns r0, r4 /* invert to get final result */ + qspi_abort /* to idle state */ + .align 2 /* align to word, bkpt is 4 words */ + bkpt #0 /* before code end for exit_point */ + .align 2 /* align to word */ + + .space 4 /* not used */ +ccr_page_read: + .space 4 /* QSPI_CCR value for read command */ + .space 4 /* not used */ + .space 4 /* not used */ diff --git a/contrib/loade... [truncated message content] |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-07 20:55:09
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 475f42051e13d64bc4d1960306ad1d2ea3c7962a (commit) via 1f6efaada0686f7e9e6164919eb739892855d327 (commit) via ba564bda6694769b95e22808982d087c779e6dd9 (commit) via 384e90b06b5005aa04d695b8a67c81a0af646082 (commit) via ad06fba6f07ceaaf88845658c47a8f50888e413e (commit) from 3cf95a9d026ec901008e6290eb0ad45557e45680 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 475f42051e13d64bc4d1960306ad1d2ea3c7962a Author: Antonio Borneo <bor...@gm...> Date: Sat Oct 31 14:55:10 2020 +0100 stlink: fix computation of trace prescaler Use integer rounding for the computation of prescaler. Improve the test of prescaler range, knowing its value would be decremented before being written in TPIU ACPR. Change-Id: I041dde1dca41323904e36a6b6975028a6de902b3 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5909 Tested-by: jenkins diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 8ab73cd12..c54e2cc19 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2989,7 +2989,6 @@ static int stlink_config_trace(void *handle, bool enabled, uint16_t *prescaler) { struct stlink_usb_handle_s *h = handle; - uint16_t presc; if (enabled && (!(h->version.flags & STLINK_F_HAS_TRACE) || pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) { @@ -3012,12 +3011,17 @@ static int stlink_config_trace(void *handle, bool enabled, if (!*trace_freq) *trace_freq = max_trace_freq; - presc = traceclkin_freq / *trace_freq; - - if (traceclkin_freq % *trace_freq > 0) - presc++; + unsigned int presc = (traceclkin_freq + *trace_freq / 2) / *trace_freq; + if (presc == 0 || presc > TPIU_ACPR_MAX_SWOSCALER + 1) { + LOG_ERROR("SWO frequency is not suitable. Please choose a different " + "frequency."); + return ERROR_FAIL; + } - if (presc > TPIU_ACPR_MAX_SWOSCALER) { + /* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */ + unsigned int max_deviation = (traceclkin_freq * 3) / 100; + if (presc * *trace_freq < traceclkin_freq - max_deviation || + presc * *trace_freq > traceclkin_freq + max_deviation) { LOG_ERROR("SWO frequency is not suitable. Please choose a different " "frequency."); return ERROR_FAIL; commit 1f6efaada0686f7e9e6164919eb739892855d327 Author: Antonio Borneo <bor...@gm...> Date: Fri Oct 30 15:03:37 2020 +0100 stlink: fix max SWV baudrate on stlink v3 While stlink v2 anly accept till to 2 MHz for SWV baudrate, stlink v3 accepts up to 24 MHz. Check the stlink version and use the respective max value. Change-Id: I911207a35983b6acf0b901059076dd31f70e6290 Signed-off-by: Antonio Borneo <bor...@gm...> Reported-by: Pawel <phr...@us...> Fixes: https://sourceforge.net/p/openocd/tickets/283/ Reviewed-on: http://openocd.zylin.com/5908 Tested-by: jenkins diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 48db3e611..8ab73cd12 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -299,6 +299,7 @@ struct stlink_usb_handle_s { #define STLINK_TRACE_SIZE 4096 #define STLINK_TRACE_MAX_HZ 2000000 +#define STLINK_V3_TRACE_MAX_HZ 24000000 #define STLINK_V3_MAX_FREQ_NB 10 @@ -2996,17 +2997,20 @@ static int stlink_config_trace(void *handle, bool enabled, return ERROR_FAIL; } + unsigned int max_trace_freq = (h->version.stlink == 3) ? + STLINK_V3_TRACE_MAX_HZ : STLINK_TRACE_MAX_HZ; + /* Only concern ourselves with the frequency if the STlink is processing it. */ - if (enabled && *trace_freq > STLINK_TRACE_MAX_HZ) { + if (enabled && *trace_freq > max_trace_freq) { LOG_ERROR("ST-LINK doesn't support SWO frequency higher than %u", - STLINK_TRACE_MAX_HZ); + max_trace_freq); return ERROR_FAIL; } stlink_usb_trace_disable(h); if (!*trace_freq) - *trace_freq = STLINK_TRACE_MAX_HZ; + *trace_freq = max_trace_freq; presc = traceclkin_freq / *trace_freq; commit ba564bda6694769b95e22808982d087c779e6dd9 Author: Antonio Borneo <bor...@gm...> Date: Sat Oct 31 14:49:23 2020 +0100 drivers/jlink: fix check for max prescaler The value stored in TPIU ACPR is the prescaler value decremented by one. Thus, the test should verify that prescaler does not exceed the maximum ACPR value plus one. Also, zero value is not allowed for prescaler. Change-Id: I1817f04f2a310b2f413bad726f0cb9dd6a4172e2 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5907 Tested-by: jenkins Reviewed-by: Adrian M Negreanu <adr...@nx...> diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index ae8ce49c6..b915707ec 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -1270,7 +1270,7 @@ static bool calculate_swo_prescaler(unsigned int traceclkin_freq, uint32_t trace_freq, uint16_t *prescaler) { unsigned int presc = (traceclkin_freq + trace_freq / 2) / trace_freq; - if (presc > TPIU_ACPR_MAX_SWOSCALER) + if (presc == 0 || presc > TPIU_ACPR_MAX_SWOSCALER + 1) return false; /* Probe's UART speed must be within 3% of the TPIU's SWO baud rate. */ @@ -1296,7 +1296,7 @@ static bool detect_swo_freq_and_prescaler(struct jaylink_swo_speed speed, *trace_freq = speed.freq / divider; presc = ((1.0 - SWO_MAX_FREQ_DEV) * traceclkin_freq) / *trace_freq + 1; - if (presc > TPIU_ACPR_MAX_SWOSCALER) + if (presc > TPIU_ACPR_MAX_SWOSCALER + 1) break; deviation = fabs(1.0 - ((double)*trace_freq * presc / traceclkin_freq)); commit 384e90b06b5005aa04d695b8a67c81a0af646082 Author: Antonio Borneo <bor...@gm...> Date: Sun Nov 1 15:39:23 2020 +0100 build: fix build with --enable-minidriver-dummy Commit 462c01206692 ("Add complete JTAG debug logging.") breaks the build for minidriver, that is enabled either on zy1000 build and on minidriver-dummy build. The check on BUILD_ZY1000 was added to pass the auto-build in jenkins. While the build issue with minidriver-dummy was known, as reported in the comment, it was not addressed and got ignored for slightly more than one year. Use the macro HAVE_JTAG_MINIDRIVER_H in place of BUILD_ZY1000 to take in account both builds that require the minidriver. Fix also the build in case configure enables the HLA drivers due to autodetection of libusb. The HLA drivers would not be in the build and the function transport_is_hla() would be missing. Change-Id: I1d85c5fa247bf4a85aba29b233c0b573b46665bc Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5911 Tested-by: jenkins diff --git a/src/jtag/core.c b/src/jtag/core.c index f0f74eb80..5abf832f8 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -953,12 +953,12 @@ int default_interface_jtag_execute_queue(void) int result = jtag->jtag_ops->execute_queue(); -#if !BUILD_ZY1000 +#if !HAVE_JTAG_MINIDRIVER_H /* Only build this if we use a regular driver with a command queue. * Otherwise jtag_command_queue won't be found at compile/link time. Its * definition is in jtag/commands.c, which is only built/linked by * jtag/Makefile.am if MINIDRIVER_DUMMY || !MINIDRIVER, but those variables - * aren't accessible here. */ + * aren't accessible here. Use HAVE_JTAG_MINIDRIVER_H */ struct jtag_command *cmd = jtag_command_queue; while (debug_level >= LOG_LVL_DEBUG_IO && cmd) { switch (cmd->type) { diff --git a/src/transport/transport.h b/src/transport/transport.h index e04f78063..6bf6aaced 100644 --- a/src/transport/transport.h +++ b/src/transport/transport.h @@ -98,7 +98,7 @@ bool transport_is_dapdirect_jtag(void); bool transport_is_dapdirect_swd(void); bool transport_is_swim(void); -#if BUILD_HLADAPTER +#if BUILD_HLADAPTER && !HAVE_JTAG_MINIDRIVER_H bool transport_is_hla(void); #else static inline bool transport_is_hla(void) commit ad06fba6f07ceaaf88845658c47a8f50888e413e Author: Antonio Borneo <bor...@gm...> Date: Sun Nov 1 01:03:44 2020 +0100 target/arm7tdmi: remove unused/deprecated function parameter The function arm7tdmi_clock_out() has one unused 'deprecated' parameter. Drop the unused 'deprecated' parameter and the FIXME above it. Change-Id: Ia8de41f5b8258825faccc737bba622e44c81a7ea Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5912 Tested-by: jenkins diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 01685ab6a..10263f40a 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -115,11 +115,9 @@ static inline int arm7tdmi_clock_out_inner(struct arm_jtag *jtag_info, uint32_t /* put an instruction in the ARM7TDMI pipeline or write the data bus, * and optionally read data - * - * FIXME remove the unused "deprecated" parameter */ static inline int arm7tdmi_clock_out(struct arm_jtag *jtag_info, - uint32_t out, uint32_t *deprecated, int breakpoint) + uint32_t out, int breakpoint) { int retval; retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE); @@ -246,35 +244,35 @@ static void arm7tdmi_change_to_arm(struct target *target, * to allow common handling of ARM and THUMB debugging */ /* fetch STR r0, [r0] */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, r0); /* MOV r0, r15 fetched, STR in Decode */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* nothing fetched, STR r0, [r0] in Execute (2) */ arm7tdmi_clock_data_in(jtag_info, pc); /* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* nothing fetched, data for LDR r0, [PC, #0] */ - arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0); + arm7tdmi_clock_out(jtag_info, 0x0, 0); /* nothing fetched, data from previous cycle is written to register */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* fetch BX */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0); /* NOP fetched, BX in Decode, MOV in Execute */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* NOP fetched, BX in Execute (1) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); jtag_execute_queue(); @@ -301,12 +299,12 @@ static void arm7tdmi_read_core_regs(struct target *target, /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0); /* fetch NOP, STM in DECODE stage */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); for (i = 0; i <= 15; i++) { if (mask & (1 << i)) @@ -329,12 +327,12 @@ static void arm7tdmi_read_core_regs_target_buffer(struct target *target, /* STMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0); /* fetch NOP, STM in DECODE stage */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, STM in EXECUTE stage (1st cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); for (i = 0; i <= 15; i++) { /* nothing fetched, STM still in EXECUTE (1 + i cycle), read databus */ @@ -360,14 +358,14 @@ static void arm7tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* MRS r0, cpsr */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0); /* STR r0, [r15] */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0); /* fetch NOP, STR in DECODE stage */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, STR in EXECUTE stage (1st cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, STR still in EXECUTE (2nd cycle) */ arm7tdmi_clock_data_in(jtag_info, xpsr); } @@ -380,25 +378,25 @@ static void arm7tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr) LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr); /* MSR1 fetched */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0); /* MSR2 fetched, MSR1 in DECODE */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0); /* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0); /* nothing fetched, MSR1 in EXECUTE (2) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0); /* nothing fetched, MSR2 in EXECUTE (2) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, MSR3 in EXECUTE (2) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* NOP fetched, MSR4 in EXECUTE (1) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, MSR4 in EXECUTE (2) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); } static void arm7tdmi_write_xpsr_im8(struct target *target, @@ -410,13 +408,13 @@ static void arm7tdmi_write_xpsr_im8(struct target *target, LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr); /* MSR fetched */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0); /* NOP fetched, MSR in DECODE */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* NOP fetched, MSR in EXECUTE (1) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, MSR in EXECUTE (2) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); } static void arm7tdmi_write_core_regs(struct target *target, @@ -429,7 +427,7 @@ static void arm7tdmi_write_core_regs(struct target *target, /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0); /* fetch NOP, LDM in DECODE stage */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); @@ -450,9 +448,9 @@ static void arm7tdmi_load_word_regs(struct target *target, uint32_t mask) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load-multiple into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0); } static void arm7tdmi_load_hword_reg(struct target *target, int num) @@ -461,9 +459,9 @@ static void arm7tdmi_load_hword_reg(struct target *target, int num) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load half-word into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0); } static void arm7tdmi_load_byte_reg(struct target *target, int num) @@ -472,9 +470,9 @@ static void arm7tdmi_load_byte_reg(struct target *target, int num) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed load byte into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0); } static void arm7tdmi_store_word_regs(struct target *target, uint32_t mask) @@ -483,9 +481,9 @@ static void arm7tdmi_store_word_regs(struct target *target, uint32_t mask) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store-multiple into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0); } static void arm7tdmi_store_hword_reg(struct target *target, int num) @@ -494,9 +492,9 @@ static void arm7tdmi_store_hword_reg(struct target *target, int num) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store half-word into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0); } static void arm7tdmi_store_byte_reg(struct target *target, int num) @@ -505,9 +503,9 @@ static void arm7tdmi_store_byte_reg(struct target *target, int num) struct arm_jtag *jtag_info = &arm7_9->jtag_info; /* put system-speed store byte into the pipeline */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0); } static void arm7tdmi_write_pc(struct target *target, uint32_t pc) @@ -518,7 +516,7 @@ static void arm7tdmi_write_pc(struct target *target, uint32_t pc) /* LDMIA r0-15, [r0] at debug speed * register values will start to appear on 4th DCLK */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0); /* fetch NOP, LDM in DECODE stage */ arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ @@ -540,7 +538,7 @@ static void arm7tdmi_branch_resume(struct target *target) struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm_jtag *jtag_info = &arm7_9->jtag_info; - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 1); arm7tdmi_clock_out_inner(jtag_info, ARMV4_5_B(0xfffffa, 0), 0); } @@ -556,53 +554,52 @@ static void arm7tdmi_branch_resume_thumb(struct target *target) /* LDMIA r0, [r0] at debug speed * register values will start to appear on 4th DCLK */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0); /* fetch NOP, LDM in DECODE stage */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* fetch NOP, LDM in EXECUTE stage (1st cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* nothing fetched, LDM in EXECUTE stage (2nd cycle) */ - arm7tdmi_clock_out(jtag_info, - buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0); + arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->pc->value, 0, 32) | 1, 0); /* nothing fetched, LDM in EXECUTE stage (3rd cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* Branch and eXchange */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0); embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in DECODE stage */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* target is now in Thumb state */ embeddedice_read_reg(dbg_stat); /* fetch NOP, BX in EXECUTE stage (1st cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0); /* target is now in Thumb state */ embeddedice_read_reg(dbg_stat); /* load r0 value */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0); /* fetch NOP, LDR in Decode */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* fetch NOP, LDR in Execute */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); /* nothing fetched, LDR in EXECUTE stage (2nd cycle) */ - arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0); + arm7tdmi_clock_out(jtag_info, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), 0); /* nothing fetched, LDR in EXECUTE stage (3rd cycle) */ - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0); embeddedice_read_reg(dbg_stat); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1); - arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 1); + arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), 0); } static void arm7tdmi_build_reg_cache(struct target *target) ----------------------------------------------------------------------- Summary of changes: src/jtag/core.c | 4 +- src/jtag/drivers/jlink.c | 4 +- src/jtag/drivers/stlink_usb.c | 26 ++++--- src/target/arm7tdmi.c | 159 +++++++++++++++++++++--------------------- src/transport/transport.h | 2 +- 5 files changed, 100 insertions(+), 95 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-07 20:54:20
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 3cf95a9d026ec901008e6290eb0ad45557e45680 (commit) via c2311cc18f0c432781c0c7d51252b2f5459e1d79 (commit) via 535f5309ba1277479d44f471655bf722e32fbb6b (commit) from 92ea7e41b9261d4d7a88d96cc3ef0a727d1059f0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3cf95a9d026ec901008e6290eb0ad45557e45680 Author: Antonio Borneo <bor...@gm...> Date: Sun Nov 1 22:06:03 2020 +0100 doc: remove reference to already dropped tftp support The only code dealing with tftp in OpenOCD was in eCos build, code already dropped in commit 39650e2273bc ("ecosboard: delete bit-rotted eCos code") almost 8 years ago. Drop tftp related documentation too. Change-Id: I0defc8f844e74c90894dca04a652dcc497a520e1 Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5913 Tested-by: jenkins Reviewed-by: Jonathan McDowell <noo...@ea...> diff --git a/doc/openocd.texi b/doc/openocd.texi index ee7186746..9903b70df 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -79,7 +79,6 @@ Free Documentation License''. * JTAG Commands:: JTAG Commands * Boundary Scan Commands:: Boundary Scan Commands * Utility Commands:: Utility Commands -* TFTP:: TFTP * GDB and OpenOCD:: Using GDB and OpenOCD * Tcl Scripting API:: Tcl Scripting API * FAQ:: Frequently Asked Questions @@ -10371,28 +10370,6 @@ For quickstart instructions run: openocd -f tools/firmware-recovery.tcl -c firmware_help @end example -@node TFTP -@chapter TFTP -@cindex TFTP -If OpenOCD runs on an embedded host (as ZY1000 does), then TFTP can -be used to access files on PCs (either the developer's PC or some other PC). - -The way this works on the ZY1000 is to prefix a filename by -"/tftp/ip/" and append the TFTP path on the TFTP -server (tftpd). For example, - -@example -load_image /tftp/10.0.0.96/c:\temp\abc.elf -@end example - -will load c:\temp\abc.elf from the developer pc (10.0.0.96) into memory as -if the file was hosted on the embedded host. - -In order to achieve decent performance, you must choose a TFTP server -that supports a packet size bigger than the default packet size (512 bytes). There -are numerous TFTP servers out there (free and commercial) and you will have to do -a bit of googling to find something that fits your requirements. - @node GDB and OpenOCD @chapter GDB and OpenOCD @cindex GDB commit c2311cc18f0c432781c0c7d51252b2f5459e1d79 Author: Antonio Borneo <bor...@gm...> Date: Thu Nov 5 09:54:11 2020 +0100 configure.ac: add libutil to the dependency list Jimtcl 0.80 (2020-10-29) adds dependency to libutil, which is part of the GNU libc. The library is searched and used by jimtcl build, but still has to be linked in by OpenOCD as indirect dependency. While OpenOCD is still using jimtcl 0.79, let's prepare to switch to the next version. Add libutil search in configure.ac. Change-Id: I5a8952161b0e5b93fc00d23be256b5274d31e08c Signed-off-by: Antonio Borneo <bor...@gm...> Reviewed-on: http://openocd.zylin.com/5922 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> diff --git a/configure.ac b/configure.ac index 055833a7f..3e49213cc 100644 --- a/configure.ac +++ b/configure.ac @@ -44,6 +44,7 @@ AC_TYPE_LONG_LONG_INT AC_SEARCH_LIBS([ioperm], [ioperm]) AC_SEARCH_LIBS([dlopen], [dl]) +AC_SEARCH_LIBS([openpty], [util]) AC_CHECK_HEADERS([sys/socket.h]) AC_CHECK_HEADERS([elf.h]) commit 535f5309ba1277479d44f471655bf722e32fbb6b Author: Alberto GarciÌa Hierro <al...@ga...> Date: Tue Oct 20 16:13:17 2020 +0100 stm32h7x: Fix reset with non-HLA interfaces on macOS regsub doesn't work correctly on macOS Catalina, which results in an incorrect CHIPNAME derived from the current target. Since regsub is only used by this target, replace it with a simple string search for '.' followed by a substring. This is funcionally equivalent to what the regular expression was doing, but instead relies in simpler string operations that should have little to no differences between systems. Also, refactor CHIPNAME detection into proc stm32h7x_chipname, so it's always retrieved in the same way without duplicating the code. Change-Id: Ia9f63f56b508688e74278b022eaec47e503916e7 Signed-off-by: Alberto Garcia Hierro <al...@ga...> Reviewed-on: http://openocd.zylin.com/5872 Tested-by: jenkins Reviewed-by: Tarek BOCHKATI <tar...@gm...> Reviewed-by: Christopher Head <ch...@za...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/target/stm32h7x.cfg b/tcl/target/stm32h7x.cfg index 4a04929aa..763a7857a 100644 --- a/tcl/target/stm32h7x.cfg +++ b/tcl/target/stm32h7x.cfg @@ -175,10 +175,19 @@ $_CHIPNAME.cpu0 configure -event reset-init { adapter speed 4000 } +# get _CHIPNAME from current target +proc stm32h7x_get_chipname {} { + set t [target current] + set sep [string last "." $t] + if {$sep == -1} { + return $t + } + return [string range $t 0 [expr $sep - 1]] +} + if {[set $_CHIPNAME.DUAL_CORE]} { $_CHIPNAME.cpu1 configure -event examine-end { - # get _CHIPNAME from the current target - set _CHIPNAME [regsub ".cpu\\d$" [target current] ""] + set _CHIPNAME [stm32h7x_get_chipname] global $_CHIPNAME.USE_CTI # Stop watchdog counters during halt @@ -214,8 +223,7 @@ proc stm32h7x_mmw {used_target reg setbits clearbits} { proc stm32h7x_dbgmcu_mmw {reg_offset setbits clearbits} { # use $_CHIPNAME.ap2 if possible, and use the proper dbgmcu base address if {![using_hla]} { - # get _CHIPNAME from the current target - set _CHIPNAME [regsub ".(cpu|ap)\\d*$" [target current] ""] + set _CHIPNAME [stm32h7x_get_chipname] set used_target $_CHIPNAME.ap2 set reg_addr [expr 0xE00E1000 + $reg_offset] } { @@ -238,8 +246,7 @@ if {[set $_CHIPNAME.USE_CTI]} { $_CHIPNAME.cpu1 configure -event debug-halted { stm32h7x_cti_prepare_restart_all } proc stm32h7x_cti_start {} { - # get _CHIPNAME from the current target - set _CHIPNAME [regsub ".cpu\\d$" [target current] ""] + set _CHIPNAME [stm32h7x_get_chipname] # Configure Cores' CTIs to halt each other # TRIGIN0 (DBGTRIGGER) and TRIGOUT0 (EDBGRQ) at CTM_CHANNEL_0 @@ -254,8 +261,7 @@ if {[set $_CHIPNAME.USE_CTI]} { } proc stm32h7x_cti_stop {} { - # get _CHIPNAME from the current target - set _CHIPNAME [regsub ".cpu\\d$" [target current] ""] + set _CHIPNAME [stm32h7x_get_chipname] $_CHIPNAME.cti0 enable off $_CHIPNAME.cti1 enable off @@ -267,8 +273,7 @@ if {[set $_CHIPNAME.USE_CTI]} { } proc stm32h7x_cti_prepare_restart {cti} { - # get _CHIPNAME from the current target - set _CHIPNAME [regsub ".cpu\\d$" [target current] ""] + set _CHIPNAME [stm32h7x_get_chipname] # Acknowlodge EDBGRQ at TRIGOUT0 $_CHIPNAME.$cti write INACK 0x01 ----------------------------------------------------------------------- Summary of changes: configure.ac | 1 + doc/openocd.texi | 23 ----------------------- tcl/target/stm32h7x.cfg | 25 +++++++++++++++---------- 3 files changed, 16 insertions(+), 33 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-07 20:53:21
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 92ea7e41b9261d4d7a88d96cc3ef0a727d1059f0 (commit) via 73746d78b7bd582bab26cebdcf78299b8da99a62 (commit) from 6dbfdcd00f190b79f24a7c231137fb5eea52bc95 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 92ea7e41b9261d4d7a88d96cc3ef0a727d1059f0 Author: Kevin Yang <kan...@go...> Date: Mon Oct 12 15:33:47 2020 -0700 target: Examine subsequent targets after failure When a target examination fails, continue to examine subsequent targets. Return the number of targets that failed to examine. Change-Id: I883a0c445edc7eb00f496b79271d773771ec6b66 Signed-off-by: Kevin Yang <kan...@go...> Reviewed-on: http://openocd.zylin.com/5855 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/target.c b/src/target/target.c index 39575b01c..3b1c666e5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -766,9 +766,11 @@ int target_examine(void) if (target->defer_examine) continue; - retval = target_examine_one(target); - if (retval != ERROR_OK) - return retval; + int retval2 = target_examine_one(target); + if (retval2 != ERROR_OK) { + LOG_WARNING("target %s examination failed", target_name(target)); + retval = retval2; + } } return retval; } commit 73746d78b7bd582bab26cebdcf78299b8da99a62 Author: Marc Schink <de...@za...> Date: Tue Nov 3 16:11:48 2020 +0100 target/image: Use proper data types While at it, fix some coding style issues. Change-Id: Id521394d89e0bf787a6f812701c2cc0fe7e4e63f Signed-off-by: Marc Schink <de...@za...> Reviewed-on: http://openocd.zylin.com/5919 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index d56301351..6182a5f82 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -702,7 +702,7 @@ int flash_write_unlock(struct target *target, struct image *image, { int retval = ERROR_OK; - int section; + unsigned int section; uint32_t section_offset; struct flash_bank *c; int *padding; @@ -727,8 +727,8 @@ int flash_write_unlock(struct target *target, struct image *image, * whereas an image can have sections out of order. */ struct imagesection **sections = malloc(sizeof(struct imagesection *) * image->num_sections); - int i; - for (i = 0; i < image->num_sections; i++) + + for (unsigned int i = 0; i < image->num_sections; i++) sections[i] = &image->sections[i]; qsort(sections, image->num_sections, sizeof(struct imagesection *), @@ -738,7 +738,7 @@ int flash_write_unlock(struct target *target, struct image *image, while (section < image->num_sections) { uint32_t buffer_idx; uint8_t *buffer; - int section_last; + unsigned int section_last; target_addr_t run_address = sections[section]->base_address + section_offset; uint32_t run_size = sections[section]->size - section_offset; int pad_bytes = 0; diff --git a/src/flash/nor/lpc2900.c b/src/flash/nor/lpc2900.c index c8e885aba..6596cde94 100644 --- a/src/flash/nor/lpc2900.c +++ b/src/flash/nor/lpc2900.c @@ -635,9 +635,9 @@ COMMAND_HANDLER(lpc2900_handle_write_custom_command) /* The image will always start at offset 0 */ struct image image; - image.base_address_set = 1; + image.base_address_set = true; image.base_address = 0; - image.start_address_set = 0; + image.start_address_set = false; const char *filename = CMD_ARGV[1]; const char *type = (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL; diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 386d73e39..87c8cede7 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -441,14 +441,14 @@ COMMAND_HANDLER(handle_flash_write_image_command) duration_start(&bench); if (CMD_ARGC >= 2) { - image.base_address_set = 1; + image.base_address_set = true; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], image.base_address); } else { - image.base_address_set = 0; + image.base_address_set = false; image.base_address = 0x0; } - image.start_address_set = 0; + image.start_address_set = false; retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index 4bc605171..fd08c1661 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -393,7 +393,7 @@ static int ulink_load_firmware_and_renumerate(struct ulink **device, static int ulink_load_firmware(struct ulink *device, const char *filename) { struct image ulink_firmware_image; - int ret, i; + int ret; ret = ulink_cpu_reset(device, CPU_RESET); if (ret != ERROR_OK) { @@ -402,7 +402,7 @@ static int ulink_load_firmware(struct ulink *device, const char *filename) } ulink_firmware_image.base_address = 0; - ulink_firmware_image.base_address_set = 0; + ulink_firmware_image.base_address_set = false; ret = image_open(&ulink_firmware_image, filename, "ihex"); if (ret != ERROR_OK) { @@ -411,7 +411,7 @@ static int ulink_load_firmware(struct ulink *device, const char *filename) } /* Download all sections in the image to ULINK */ - for (i = 0; i < ulink_firmware_image.num_sections; i++) { + for (unsigned int i = 0; i < ulink_firmware_image.num_sections; i++) { ret = ulink_write_firmware_section(device, &ulink_firmware_image, i); if (ret != ERROR_OK) return ret; diff --git a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c index f8ff66e2f..6f15fa70a 100644 --- a/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c +++ b/src/jtag/drivers/usb_blaster/ublast2_access_libusb.c @@ -134,7 +134,7 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev, } ublast2_firmware_image.base_address = 0; - ublast2_firmware_image.base_address_set = 0; + ublast2_firmware_image.base_address_set = false; int ret = image_open(&ublast2_firmware_image, low->firmware_path, "ihex"); if (ret != ERROR_OK) { @@ -162,7 +162,7 @@ static int load_usb_blaster_firmware(struct libusb_device_handle *libusb_dev, 100); /* Download all sections in the image to ULINK */ - for (int i = 0; i < ublast2_firmware_image.num_sections; i++) { + for (unsigned int i = 0; i < ublast2_firmware_image.num_sections; i++) { ret = ublast2_write_firmware_section(libusb_dev, &ublast2_firmware_image, i); if (ret != ERROR_OK) { diff --git a/src/target/etm.c b/src/target/etm.c index 5d079ffa8..93dbd2948 100644 --- a/src/target/etm.c +++ b/src/target/etm.c @@ -650,7 +650,6 @@ static struct etm_capture_driver *etm_capture_drivers[] = { static int etm_read_instruction(struct etm_context *ctx, struct arm_instruction *instruction) { - int i; int section = -1; size_t size_read; uint32_t opcode; @@ -660,7 +659,7 @@ static int etm_read_instruction(struct etm_context *ctx, struct arm_instruction return ERROR_TRACE_IMAGE_UNAVAILABLE; /* search for the section the current instruction belongs to */ - for (i = 0; i < ctx->image->num_sections; i++) { + for (unsigned int i = 0; i < ctx->image->num_sections; i++) { if ((ctx->image->sections[i].base_address <= ctx->current_pc) && (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc)) { @@ -1683,15 +1682,15 @@ COMMAND_HANDLER(handle_etm_image_command) } etm_ctx->image = malloc(sizeof(struct image)); - etm_ctx->image->base_address_set = 0; - etm_ctx->image->start_address_set = 0; + etm_ctx->image->base_address_set = false; + etm_ctx->image->start_address_set = false; /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { - etm_ctx->image->base_address_set = 1; + etm_ctx->image->base_address_set = true; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], etm_ctx->image->base_address); } else - etm_ctx->image->base_address_set = 0; + etm_ctx->image->base_address_set = false; if (image_open(etm_ctx->image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) { diff --git a/src/target/image.c b/src/target/image.c index 8160e5f92..0b7debaef 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -124,7 +124,6 @@ static int image_ihex_buffer_complete_inner(struct image *image, uint32_t full_address; uint32_t cooked_bytes; bool end_rec = false; - int i; /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ @@ -207,7 +206,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, /* copy section information */ image->sections = malloc(sizeof(struct imagesection) * image->num_sections); - for (i = 0; i < image->num_sections; i++) { + for (unsigned int i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; image->sections[i].base_address = section[i].base_address; image->sections[i].size = section[i].size; @@ -294,7 +293,7 @@ static int image_ihex_buffer_complete_inner(struct image *image, cal_checksum += (uint8_t)start_address; bytes_read += 8; - image->start_address_set = 1; + image->start_address_set = true; image->start_address = be_to_h_u32((uint8_t *)&start_address); } else { LOG_ERROR("unhandled IHEX record type: %i", (int)record_type); @@ -471,7 +470,7 @@ static int image_elf_read_headers(struct image *image) } } - image->start_address_set = 1; + image->start_address_set = true; image->start_address = field32(elf, elf->header->e_entry); return ERROR_OK; @@ -529,7 +528,6 @@ static int image_mot_buffer_complete_inner(struct image *image, uint32_t full_address; uint32_t cooked_bytes; bool end_rec = false; - int i; /* we can't determine the number of sections that we'll have to create ahead of time, * so we locally hold them until parsing is finished */ @@ -658,7 +656,7 @@ static int image_mot_buffer_complete_inner(struct image *image, /* copy section information */ image->sections = malloc(sizeof(struct imagesection) * image->num_sections); - for (i = 0; i < image->num_sections; i++) { + for (unsigned int i = 0; i < image->num_sections; i++) { image->sections[i].private = section[i].private; image->sections[i].base_address = section[i].base_address; image->sections[i].size = section[i].size; @@ -821,21 +819,20 @@ int image_open(struct image *image, const char *url, const char *type_string) } } else if (image->type == IMAGE_BUILDER) { image->num_sections = 0; - image->base_address_set = 0; + image->base_address_set = false; image->sections = NULL; image->type_private = NULL; } if (image->base_address_set) { /* relocate */ - int section; - for (section = 0; section < image->num_sections; section++) + for (unsigned int section = 0; section < image->num_sections; section++) image->sections[section].base_address += image->base_address; /* we're done relocating. The two statements below are mainly * for documentation purposes: stop anyone from empirically * thinking they should use these values henceforth. */ image->base_address = 0; - image->base_address_set = 0; + image->base_address_set = false; } return retval; @@ -1009,9 +1006,7 @@ void image_close(struct image *image) free(image_mot->buffer); image_mot->buffer = NULL; } else if (image->type == IMAGE_BUILDER) { - int i; - - for (i = 0; i < image->num_sections; i++) { + for (unsigned int i = 0; i < image->num_sections; i++) { free(image->sections[i].private); image->sections[i].private = NULL; } diff --git a/src/target/image.h b/src/target/image.h index 9907a5f3f..765d29022 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -55,11 +55,11 @@ struct imagesection { struct image { enum image_type type; /* image type (plain, ihex, ...) */ void *type_private; /* type private data */ - int num_sections; /* number of sections contained in the image */ + unsigned int num_sections; /* number of sections contained in the image */ struct imagesection *sections; /* array of sections */ - int base_address_set; /* whether the image has a base address set (for relocation purposes) */ + bool base_address_set; /* whether the image has a base address set (for relocation purposes) */ long long base_address; /* base address, if one is set */ - int start_address_set; /* whether the image has a start address (entry point) associated */ + bool start_address_set; /* whether the image has a start address (entry point) associated */ uint32_t start_address; /* start address, if one is set */ }; diff --git a/src/target/target.c b/src/target/target.c index da0c943bf..39575b01c 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3404,11 +3404,11 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image->base_address = addr; - image->base_address_set = 1; + image->base_address_set = true; } else - image->base_address_set = 0; + image->base_address_set = false; - image->start_address_set = 0; + image->start_address_set = false; if (CMD_ARGC >= 4) COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address); @@ -3431,7 +3431,6 @@ COMMAND_HANDLER(handle_load_image_command) uint32_t image_size; target_addr_t min_address = 0; target_addr_t max_address = -1; - int i; struct image image; int retval = CALL_COMMAND_HANDLER(parse_load_image_command_CMD_ARGV, @@ -3449,7 +3448,7 @@ COMMAND_HANDLER(handle_load_image_command) image_size = 0x0; retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD, @@ -3582,7 +3581,6 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - int i; int retval; uint32_t checksum = 0; uint32_t mem_checksum = 0; @@ -3606,13 +3604,13 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver target_addr_t addr; COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image.base_address = addr; - image.base_address_set = 1; + image.base_address_set = true; } else { - image.base_address_set = 0; + image.base_address_set = false; image.base_address = 0x0; } - image.start_address_set = 0; + image.start_address_set = false; retval = image_open(&image, CMD_ARGV[0], (CMD_ARGC == 3) ? CMD_ARGV[2] : NULL); if (retval != ERROR_OK) @@ -3621,12 +3619,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver image_size = 0x0; int diffs = 0; retval = ERROR_OK; - for (i = 0; i < image.num_sections; i++) { + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD, - "error allocating buffer for section (%d bytes)", - (int)(image.sections[i].size)); + "error allocating buffer for section (%" PRIu32 " bytes)", + image.sections[i].size); break; } retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt); @@ -5871,7 +5869,6 @@ COMMAND_HANDLER(handle_fast_load_image_command) uint32_t image_size; target_addr_t min_address = 0; target_addr_t max_address = -1; - int i; struct image image; @@ -5897,7 +5894,7 @@ COMMAND_HANDLER(handle_fast_load_image_command) return ERROR_FAIL; } memset(fastload, 0, sizeof(struct FastLoad)*image.num_sections); - for (i = 0; i < image.num_sections; i++) { + for (unsigned int i = 0; i < image.num_sections; i++) { buffer = malloc(image.sections[i].size); if (buffer == NULL) { command_print(CMD, "error allocating buffer for section (%d bytes)", diff --git a/src/target/xscale.c b/src/target/xscale.c index 6d1d426d5..aaaed0ebb 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -2582,7 +2582,6 @@ static int xscale_read_instruction(struct target *target, uint32_t pc, struct arm_instruction *instruction) { struct xscale_common *const xscale = target_to_xscale(target); - int i; int section = -1; size_t size_read; uint32_t opcode; @@ -2592,7 +2591,7 @@ static int xscale_read_instruction(struct target *target, uint32_t pc, return ERROR_TRACE_IMAGE_UNAVAILABLE; /* search for the section the current instruction belongs to */ - for (i = 0; i < xscale->trace.image->num_sections; i++) { + for (unsigned int i = 0; i < xscale->trace.image->num_sections; i++) { if ((xscale->trace.image->sections[i].base_address <= pc) && (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > pc)) { @@ -3428,15 +3427,15 @@ COMMAND_HANDLER(xscale_handle_trace_image_command) } xscale->trace.image = malloc(sizeof(struct image)); - xscale->trace.image->base_address_set = 0; - xscale->trace.image->start_address_set = 0; + xscale->trace.image->base_address_set = false; + xscale->trace.image->start_address_set = false; /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { - xscale->trace.image->base_address_set = 1; + xscale->trace.image->base_address_set = true; COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address); } else - xscale->trace.image->base_address_set = 0; + xscale->trace.image->base_address_set = false; if (image_open(xscale->trace.image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) { ----------------------------------------------------------------------- Summary of changes: src/flash/nor/core.c | 8 +++--- src/flash/nor/lpc2900.c | 4 +-- src/flash/nor/tcl.c | 6 ++-- src/jtag/drivers/ulink.c | 6 ++-- .../drivers/usb_blaster/ublast2_access_libusb.c | 4 +-- src/target/etm.c | 11 ++++---- src/target/image.c | 21 ++++++-------- src/target/image.h | 6 ++-- src/target/target.c | 33 +++++++++++----------- src/target/xscale.c | 11 ++++---- 10 files changed, 51 insertions(+), 59 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-07 20:52:34
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 6dbfdcd00f190b79f24a7c231137fb5eea52bc95 (commit) via 2edcb065d45b7f0ee8adf260c792e0c2f3829a60 (commit) via 25e1c0f4c054eef25d1b9ad2507ee33faa05b345 (commit) from 990a01b70203a512b120e562dd991c29ee9201b2 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 6dbfdcd00f190b79f24a7c231137fb5eea52bc95 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Nov 2 16:31:27 2020 +0100 GitHub/WorkFlow: fix for CVE-2020-15228 According the CVE-2020-15228 documented in: - https://github.com/advisories/GHSA-mfwh-5m23-j46w - https://nvd.nist.gov/vuln/detail/CVE-2020-15228 the `set-env` commands will be disabled in the near future and should be replaced by: echo "FOO=BAR" >> $GITHUB_ENV idem for `add-path`, should be replaced by: echo "/path/to/add" >> $GITHUB_PATH Change-Id: I725c9ccd861a0d1580ac22491b6d716ec65973d1 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5866 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 123ee66bd..e9a95ffb5 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -24,7 +24,7 @@ jobs: mkdir -p $DL_DIR && cd $DL_DIR wget "https://github.com/libusb/libusb/releases/download/v${LIBUSB1_VER}/libusb-${LIBUSB1_VER}.tar.bz2" tar -xjf libusb-${LIBUSB1_VER}.tar.bz2 - echo "::set-env name=LIBUSB1_SRC::$PWD/libusb-${LIBUSB1_VER}" + echo "LIBUSB1_SRC=$PWD/libusb-${LIBUSB1_VER}" >> $GITHUB_ENV - name: Prepare hidapi env: HIDAPI_VER: 0.9.0 @@ -34,7 +34,7 @@ jobs: tar -xzf hidapi-${HIDAPI_VER}.tar.gz cd hidapi-hidapi-${HIDAPI_VER} ./bootstrap - echo "::set-env name=HIDAPI_SRC::$PWD" + echo "HIDAPI_SRC=$PWD" >> $GITHUB_ENV - name: Prepare libftdi env: LIBFTDI_VER: 1.4 @@ -42,7 +42,7 @@ jobs: mkdir -p $DL_DIR && cd $DL_DIR wget "http://www.intra2net.com/en/developer/libftdi/download/libftdi1-${LIBFTDI_VER}.tar.bz2" tar -xjf libftdi1-${LIBFTDI_VER}.tar.bz2 - echo "::set-env name=LIBFTDI_SRC::$PWD/libftdi1-${LIBFTDI_VER}" + echo "LIBFTDI_SRC=$PWD/libftdi1-${LIBFTDI_VER}" >> $GITHUB_ENV - name: Prepare capstone env: CAPSTONE_VER: 4.0.2 @@ -78,8 +78,8 @@ jobs: # prepare the artifact ARTIFACT="openocd-${OPENOCD_TAG}-${HOST}.tar.gz" tar -czf $ARTIFACT * - echo "::set-env name=ARTIFACT_NAME::$ARTIFACT" - echo "::set-env name=ARTIFACT_PATH::$PWD/$ARTIFACT" + echo "ARTIFACT_NAME=$ARTIFACT" >> $GITHUB_ENV + echo "ARTIFACT_PATH=$PWD/$ARTIFACT" >> $GITHUB_ENV - name: Publish OpenOCD packaged for windows uses: actions/upload-artifact@v1 with: commit 2edcb065d45b7f0ee8adf260c792e0c2f3829a60 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Nov 2 12:58:15 2020 +0100 Github: add capstone in windows snapshots Change-Id: I402c18ff72de715ce4012bce3df72aaed7159d50 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5915 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml index 2b73f9c8c..123ee66bd 100644 --- a/.github/workflows/snapshot.yml +++ b/.github/workflows/snapshot.yml @@ -43,6 +43,16 @@ jobs: wget "http://www.intra2net.com/en/developer/libftdi/download/libftdi1-${LIBFTDI_VER}.tar.bz2" tar -xjf libftdi1-${LIBFTDI_VER}.tar.bz2 echo "::set-env name=LIBFTDI_SRC::$PWD/libftdi1-${LIBFTDI_VER}" + - name: Prepare capstone + env: + CAPSTONE_VER: 4.0.2 + run: | + mkdir -p $DL_DIR && cd $DL_DIR + CAPSTONE_NAME=${CAPSTONE_VER} + CAPSTONE_FOLDER=capstone-${CAPSTONE_VER} + wget "https://github.com/aquynh/capstone/archive/${CAPSTONE_VER}.tar.gz" + tar -xzf ${CAPSTONE_VER}.tar.gz + echo "CAPSTONE_SRC=$PWD/capstone-${CAPSTONE_VER}" >> $GITHUB_ENV - name: Package OpenOCD for windows env: MAKE_JOBS: 2 @@ -50,6 +60,7 @@ jobs: LIBUSB1_CONFIG: --enable-shared --enable-static HIDAPI_CONFIG: --enable-shared --disable-static --disable-testgui LIBFTDI_CONFIG: "-DCMAKE_TOOLCHAIN_FILE='${{ env.LIBFTDI_SRC }}/cmake/Toolchain-i686-w64-mingw32.cmake' -DBUILD_TESTS:BOOL=off -DFTDIPP:BOOL=off -DPYTHON_BINDINGS:BOOL=off -DEXAMPLES:BOOL=off -DDOCUMENTATION:BOOL=off -DFTDI_EEPROM:BOOL=off" + CAPSTONE_CONFIG: "CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_STATIC=yes CAPSTONE_SHARED=no" run: | # set snapshot tag OPENOCD_TAG="`git tag --points-at HEAD`" commit 25e1c0f4c054eef25d1b9ad2507ee33faa05b345 Author: Tarek BOCHKATI <tar...@gm...> Date: Mon Nov 2 16:12:11 2020 +0100 contrib/cross-build.sh: build capstone from source tested with capstone 4.0.2, with the following options CAPSTONE_CONFIG="CAPSTONE_ARCHS=arm,aarch64 CAPSTONE_BUILD_CORE_ONLY=yes CAPSTONE_STATIC=yes CAPSTONE_SHARED=no" Change-Id: I40297772664e85c3d0f9358c85bfd901b5eba8b1 Signed-off-by: Tarek BOCHKATI <tar...@gm...> Reviewed-on: http://openocd.zylin.com/5914 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/contrib/cross-build.sh b/contrib/cross-build.sh index 821d48ec7..8b31a3f00 100755 --- a/contrib/cross-build.sh +++ b/contrib/cross-build.sh @@ -14,8 +14,8 @@ # paths refer to the build file system. # # This script is probably more useful as a reference than as a complete build -# tool but for some configurations it may be usable as-is. It only cross- -# builds libusb-1.0, hidapi and libftdi from source, but the script can be +# tool but for some configurations it may be usable as-is. It only cross-builds +# libusb-1.0, hidapi, libftdi and capstone from source, but the script can be # extended to build other prerequisites in a similar manner. # # Usage: @@ -39,17 +39,20 @@ WORK_DIR=$PWD : ${LIBUSB1_SRC:=/path/to/libusb1} : ${HIDAPI_SRC:=/path/to/hidapi} : ${LIBFTDI_SRC:=/path/to/libftdi} +: ${CAPSTONE_SRC:=/path/to/capstone} OPENOCD_SRC=`readlink -m $OPENOCD_SRC` LIBUSB1_SRC=`readlink -m $LIBUSB1_SRC` HIDAPI_SRC=`readlink -m $HIDAPI_SRC` LIBFTDI_SRC=`readlink -m $LIBFTDI_SRC` +CAPSTONE_SRC=`readlink -m $CAPSTONE_SRC` HOST_TRIPLET=$1 BUILD_DIR=$WORK_DIR/$HOST_TRIPLET-build LIBUSB1_BUILD_DIR=$BUILD_DIR/libusb1 HIDAPI_BUILD_DIR=$BUILD_DIR/hidapi LIBFTDI_BUILD_DIR=$BUILD_DIR/libftdi +CAPSTONE_BUILD_DIR=$BUILD_DIR/capstone OPENOCD_BUILD_DIR=$BUILD_DIR/openocd ## Root of host file tree @@ -129,6 +132,26 @@ if [ -d $LIBFTDI_SRC ] ; then make install DESTDIR=$SYSROOT fi +# capstone build & install into sysroot +if [ -d $CAPSTONE_SRC ] ; then + mkdir -p $CAPSTONE_BUILD_DIR + cd $CAPSTONE_BUILD_DIR + cp -r $CAPSTONE_SRC/* . + make install DESTDIR=$SYSROOT PREFIX=$PREFIX \ + CROSS="${HOST_TRIPLET}-" \ + $CAPSTONE_CONFIG + # fix the generated capstone.pc + CAPSTONE_PC_FILE=${SYSROOT}${PREFIX}/lib/pkgconfig/capstone.pc + sed -i '/^libdir=/d' $CAPSTONE_PC_FILE + sed -i '/^includedir=/d' $CAPSTONE_PC_FILE + sed -i '/^archive=/d' $CAPSTONE_PC_FILE + sed -i '1s;^;prefix=/usr \ +exec_prefix=${prefix} \ +libdir=${exec_prefix}/lib \ +includedir=${prefix}/include\n\n;' $CAPSTONE_PC_FILE +fi + + # OpenOCD build & install into sysroot mkdir -p $OPENOCD_BUILD_DIR cd $OPENOCD_BUILD_DIR ----------------------------------------------------------------------- Summary of changes: .github/workflows/snapshot.yml | 21 ++++++++++++++++----- contrib/cross-build.sh | 27 +++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 7 deletions(-) hooks/post-receive -- Main OpenOCD repository |
From: OpenOCD-Gerrit <ope...@us...> - 2020-11-07 20:51:42
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 990a01b70203a512b120e562dd991c29ee9201b2 (commit) via 8e281b76ea26f5da79875ad927c4660fb7b1502b (commit) via 850e85fa6fec275cb9f2bc76faefee51136e878e (commit) from 9cce6b3c763e883faea545b9ffbda19ec8164804 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 990a01b70203a512b120e562dd991c29ee9201b2 Author: Jonathan McDowell <no...@ea...> Date: Sun Nov 1 12:10:23 2020 +0000 tcl/interface/ftdi: Add HIE JTAG Debugger config Change-Id: Ibb7a2bb8807c442394982e89258874557a2baaad Signed-off-by: Jonathan McDowell <no...@ea...> Reviewed-on: http://openocd.zylin.com/5910 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/tcl/interface/ftdi/hie-jtag.cfg b/tcl/interface/ftdi/hie-jtag.cfg new file mode 100644 index 000000000..39af87d89 --- /dev/null +++ b/tcl/interface/ftdi/hie-jtag.cfg @@ -0,0 +1,20 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# +# Hofstädtler Industrie-Electronic (HIE) JTAG Debugger +# +# https://www.hofstaedtler.com/jtag +# + +adapter driver ftdi +ftdi_channel 0 +ftdi_vid_pid 0x0403 0x6014 +ftdi_device_desc "HIE JTAG Debugger" + +ftdi_layout_init 0x0c08 0x4f1b + +# define both Reset signals +ftdi_layout_signal nTRST -data 0x0100 -noe 0x0400 +ftdi_layout_signal nSRST -data 0x0200 -noe 0x0800 + +# Toggle USB LED +ftdi_layout_signal LED -ndata 0x4000 commit 8e281b76ea26f5da79875ad927c4660fb7b1502b Author: Marc Schink <de...@za...> Date: Tue Nov 3 13:38:59 2020 +0100 doc: Improve 'jlink usb' description Change-Id: Ica44980ac0ba8a4f0ff03b42ce37d1de861d4fb5 Signed-off-by: Marc Schink <de...@za...> Reviewed-on: http://openocd.zylin.com/5918 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/doc/openocd.texi b/doc/openocd.texi index b01e5a6c1..ee7186746 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2881,8 +2881,8 @@ The following example shows how to read 4 bytes from the EMUCOM channel 0x0: @deffn {Config} {jlink usb} <@option{0} to @option{3}> Set the USB address of the interface, in case more than one adapter is connected to the host. If not specified, USB addresses are not considered. Device -selection via USB address is deprecated and the serial number should be used -instead. +selection via USB address is not always unambiguous. It is recommended to use +the serial number instead, if possible. As a configuration command, it can be used only before 'init'. @end deffn commit 850e85fa6fec275cb9f2bc76faefee51136e878e Author: Adrian Negreanu <adr...@nx...> Date: Thu Nov 5 11:56:16 2020 +0200 semihosting: print the semihosting operation id Change-Id: If5c3568bd1c99a48ac492137f48da0d9764efe14 Signed-off-by: Adrian Negreanu <adr...@nx...> Reviewed-on: http://openocd.zylin.com/5923 Tested-by: jenkins Reviewed-by: Antonio Borneo <bor...@gm...> Reviewed-by: Jonathan McDowell <noo...@ea...> Reviewed-by: Tim Newsome <ti...@si...> diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 61f1e7801..723be577e 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -315,7 +315,7 @@ int arm_semihosting(struct target *target, int *retval) if (0 <= semihosting->op && semihosting->op <= 0x31) { *retval = semihosting_common(target); if (*retval != ERROR_OK) { - LOG_ERROR("Failed semihosting operation"); + LOG_ERROR("Failed semihosting operation (0x%02X)", semihosting->op); return 0; } } else { diff --git a/src/target/riscv/riscv_semihosting.c b/src/target/riscv/riscv_semihosting.c index 99d6c7713..c0e81eae4 100644 --- a/src/target/riscv/riscv_semihosting.c +++ b/src/target/riscv/riscv_semihosting.c @@ -140,7 +140,7 @@ semihosting_result_t riscv_semihosting(struct target *target, int *retval) if (0 <= semihosting->op && semihosting->op <= 0x31) { *retval = semihosting_common(target); if (*retval != ERROR_OK) { - LOG_ERROR("Failed semihosting operation"); + LOG_ERROR("Failed semihosting operation (0x%02X)", semihosting->op); return SEMI_ERROR; } } else { ----------------------------------------------------------------------- Summary of changes: doc/openocd.texi | 4 ++-- src/target/arm_semihosting.c | 2 +- src/target/riscv/riscv_semihosting.c | 2 +- tcl/interface/ftdi/hie-jtag.cfg | 20 ++++++++++++++++++++ 4 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 tcl/interface/ftdi/hie-jtag.cfg hooks/post-receive -- Main OpenOCD repository |