From 20e4e77cdf366dedac21ff5670c54291feadfc05 Mon Sep 17 00:00:00 2001 From: drath Date: Fri, 10 Aug 2007 19:44:06 +0000 Subject: - renamed M5960 USB JTAG to "flyswatter" - make ep93xx and at91rm9200 bitbang JTAG interfaces dependant on ARM host (thanks to Vincent Palatin) - various whitespace fixes - removed various warnings - add support for Debian GNU/kFreeBSD (thanks to Uwe Hermann) - fix OpenOCD compilation for various platforms (thanks to Uwe Hermann and Vincent Palatin) - switched order of JTAG chain examination and validation (examine first, then multiple validation tries even if examination failed) - added target_request subsystem to handle requests from the target (debug messages and tracepoints implemented, future enhancements might include semihosting, all ARM7/9 only for now) - added support for GDB vFlashXXX packets (thanks to Pavel Chromy) - added support for receiving data via ARM7/9 DCC - reworked flash writing. the 'flash write' command is now deprecated and replaced by 'flash write_binary' (old syntax and behaviour) and 'flash write_image' (write image files (bin, hex, elf, s19) to a target). - added support for AMD/ST/SST 29F400B non-cfi flashes git-svn-id: svn://svn.berlios.de/openocd/trunk@190 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- src/target/target_request.c | 270 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 src/target/target_request.c (limited to 'src/target/target_request.c') diff --git a/src/target/target_request.c b/src/target/target_request.c new file mode 100644 index 00000000..e8409020 --- /dev/null +++ b/src/target/target_request.c @@ -0,0 +1,270 @@ +/*************************************************************************** + * Copyright (C) 2007 by Dominic Rath * + * Dominic.Rath@gmx.de * + * * + * 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, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" +#include "log.h" +#include "target.h" +#include "target_request.h" +#include "binarybuffer.h" +#include "command.h" + +#include +#include + +command_t *target_request_cmd = NULL; + +int target_asciimsg(target_t *target, u32 length) +{ + char *msg = malloc(CEIL(length + 1, 4) * 4); + debug_msg_receiver_t *c = target->dbgmsg; + + target->type->target_request_data(target, CEIL(length, 4), (u8*)msg); + msg[length] = 0; + + DEBUG("%s", msg); + + while (c) + { + command_print(c->cmd_ctx, "%s", msg); + c = c->next; + } + + return ERROR_OK; +} + +int target_hexmsg(target_t *target, int size, u32 length) +{ + if (size == 1) + { + u8 *data = malloc(CEIL(length * sizeof(u8), 4) * 4); + + target->type->target_request_data(target, CEIL(length * sizeof(u8), 4), (u8*)data); + + free(data); + } + else if (size == 2) + { + u16 *data = malloc(CEIL(length * sizeof(u16), 4) * 4); + + target->type->target_request_data(target, CEIL(length * sizeof(u16), 4), (u8*)data); + + free(data); + } + else if (size == 4) + { + u32 *data = malloc(CEIL(length * sizeof(u32), 4) * 4); + + target->type->target_request_data(target, CEIL(length * sizeof(u32), 4), (u8*)data); + + free(data); + } + else + { + ERROR("invalid debug message type"); + } + + return ERROR_OK; +} + +/* handle requests from the target received by a target specific + * side-band channel (e.g. ARM7/9 DCC) + */ +int target_request(target_t *target, u32 request) +{ + target_req_cmd_t target_req_cmd = request & 0xff; + + switch (target_req_cmd) + { + case TARGET_REQ_TRACEMSG: + DEBUG("tracepoint: %i", (request & 0xffffff00) >> 8); + break; + case TARGET_REQ_DEBUGMSG: + if (((request & 0xff00) >> 8) == 0) + { + target_asciimsg(target, (request & 0xffff0000) >> 16); + } + else + { + target_hexmsg(target, (request & 0xff00) >> 8, (request & 0xffff0000) >> 16); + } + break; +/* case TARGET_REQ_SEMIHOSTING: + * break; + */ + default: + ERROR("unknown target request: %2.2x", target_req_cmd); + break; + } + + return ERROR_OK; +} + +int add_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target) +{ + debug_msg_receiver_t **p = &target->dbgmsg; + + if (target == NULL) + return ERROR_INVALID_ARGUMENTS; + + /* see if there's already a list */ + if (*p) + { + /* find end of linked list */ + p = &target->dbgmsg; + while ((*p)->next) + p = &((*p)->next); + p = &((*p)->next); + } + + /* add new debug message receiver */ + (*p) = malloc(sizeof(debug_msg_receiver_t)); + (*p)->cmd_ctx = cmd_ctx; + (*p)->next = NULL; + + return ERROR_OK; +} + +debug_msg_receiver_t* find_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target) +{ + int all_targets = 0; + debug_msg_receiver_t **p = &target->dbgmsg; + + /* if no target has been specified search all of them */ + if (target == NULL) + { + /* if no targets haven been specified */ + if (targets == NULL) + return NULL; + + target = targets; + all_targets = 1; + } + + do + { + while (*p) + { + if ((*p)->cmd_ctx == cmd_ctx) + { + return *p; + } + p = &((*p)->next); + } + + target = target->next; + } while (target && all_targets); + + return NULL; +} + +int delete_debug_msg_receiver(struct command_context_s *cmd_ctx, target_t *target) +{ + debug_msg_receiver_t **p; + debug_msg_receiver_t *c; + int all_targets = 0; + + /* if no target has been specified search all of them */ + if (target == NULL) + { + /* if no targets haven been specified */ + if (targets == NULL) + return ERROR_OK; + + target = targets; + all_targets = 1; + } + + do + { + while (c) + { + debug_msg_receiver_t *next = c->next; + if (c->cmd_ctx == cmd_ctx) + { + *p = next; + free(c); + return ERROR_OK; + } + else + p = &(c->next); + c = next; + } + + target = target->next; + } while (target && all_targets); + + return ERROR_OK; +} + +int handle_target_request_debugmsgs_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + target_t *target = get_current_target(cmd_ctx); + + int receiving = 0; + + /* see if reciever is already registered */ + if (find_debug_msg_receiver(cmd_ctx, target) != NULL) + receiving = 1; + + if (argc > 0) + { + if (!strcmp(args[0], "enable")) + { + /* don't register if this command context is already receiving */ + if (!receiving) + { + receiving = 1; + add_debug_msg_receiver(cmd_ctx, target); + } + } + else if (!strcmp(args[0], "disable")) + { + /* no need to delete a receiver if none is registered */ + if (receiving) + { + receiving = 0; + delete_debug_msg_receiver(cmd_ctx, target); + } + } + else + { + command_print(cmd_ctx, "usage: target_request debugmsgs ['enable'|'disable']"); + } + } + + command_print(cmd_ctx, "receiving debug messages from current target %s", + (receiving) ? "enabled" : "disabled"); + + return ERROR_OK; +} + +int target_request_register_commands(struct command_context_s *cmd_ctx) +{ + target_request_cmd = + register_command(cmd_ctx, NULL, "target_request", NULL, COMMAND_ANY, "target_request commands"); + + register_command(cmd_ctx, target_request_cmd, "debugmsgs", handle_target_request_debugmsgs_command, + COMMAND_EXEC, "enable/disable reception of debug messgages from target"); + + return ERROR_OK; +} -- cgit v1.2.3