-
Micah Elizabeth Scott authoredMicah Elizabeth Scott authored
libswd_log.c 7.55 KiB
/*
* $Id$
*
* Serial Wire Debug Open Library.
* Library Body File.
*
* Copyright (C) 2010-2012, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the Tomasz Boleslaw CEDRO nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
* IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.*
*
* Written by Tomasz Boleslaw CEDRO <cederom@tlen.pl>, 2010-2012;
*
*/
/** \file liblibswd_log.c */
#include "libswd.h"
/*******************************************************************************
* \defgroup libswd_log Miscelanous logging functionalities.
* @{
******************************************************************************/
/** Logging functionality can be external or internal, by default external
* function can be defined to use target program logging mechanism.
* To use internal logging mechanism simply wrap libswd_log_internal() around
* this function in application specific driver bridge file,
* see liblibswd_externs.c for examples.
*/
extern int libswd_log(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel, char *msg, ...);
/** Change log level to increase or decrease verbosity level.
* \param *libswdctx swd context.
* \param loglevel is the target verbosity level to be set.
* \return LIBSWD_OK on success or error code.
*/
int libswd_log_level_set(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel){
if (libswdctx==NULL) return LIBSWD_ERROR_NULLCONTEXT;
if (loglevel<LIBSWD_LOGLEVEL_MIN && loglevel>LIBSWD_LOGLEVEL_MAX)
return LIBSWD_ERROR_LOGLEVEL;
libswdctx->config.loglevel=loglevel;
libswd_log(libswdctx, LIBSWD_LOGLEVEL_DEBUG, "LIBSWD_D: libswd_log_level_set(libswdctx=0x%p, loglevel[%d..%d]=%d/%s)", (void*)libswdctx, LIBSWD_LOGLEVEL_MIN, LIBSWD_LOGLEVEL_MAX, loglevel, libswd_log_level_string(loglevel));
return LIBSWD_OK;
}
/** Helper function that returns loglevel name string for logging purposes.
* \param loglevel is the libswd_loglevel_t code to produce a string.
* \return char* loglevel name sring array.
*/
const char *libswd_log_level_string(libswd_loglevel_t loglevel){
switch (loglevel){
case LIBSWD_LOGLEVEL_SILENT: return "LIBSWD_LOGLEVEL_SILENT";
case LIBSWD_LOGLEVEL_ERROR: return "LIBSWD_LOGLEVEL_ERROR";
case LIBSWD_LOGLEVEL_WARNING: return "LIBSWD_LOGLEVEL_WARNING";
case LIBSWD_LOGLEVEL_NORMAL: return "LIBSWD_LOGLEVEL_NORMAL";
case LIBSWD_LOGLEVEL_INFO: return "LIBSWD_LOGLEVEL_INFO";
case LIBSWD_LOGLEVEL_DEBUG: return "LIBSWD_LOGLEVEL_DEBUG";
case LIBSWD_LOGLEVEL_PAYLOAD: return "LIBSWD_LOGLEVEL_PAYLOAD";
}
return "UNKNOWN LOGLEVEL!";
};
/** Helper function to produce operation name string for logging purposes.
* \param operation is the libswd_operation_t code to return as string.
* \return char* array with operation name string.
*/
const char *libswd_operation_string(libswd_operation_t operation){
switch(operation){
case LIBSWD_OPERATION_ENQUEUE: return "LIBSWD_OPERATION_ENQUEUE";
case LIBSWD_OPERATION_EXECUTE: return "LIBSWD_OPERATION_EXECUTE";
case LIBSWD_OPERATION_TRANSMIT_HEAD: return "LIBSWD_OPERATION_TRANSMIT_HEAD";
case LIBSWD_OPERATION_TRANSMIT_TAIL: return "LIBSWD_OPERATION_TRANSMIT_TAIL";
case LIBSWD_OPERATION_TRANSMIT_ALL: return "LIBSWD_OPERATION_TRANSMIT_ALL";
case LIBSWD_OPERATION_TRANSMIT_ONE: return "LIBSWD_OPERATION_TRANSMIT_ONE";
case LIBSWD_OPERATION_TRANSMIT_LAST: return "LIBSWD_OPERATION_TRANSMIT_LAST";
}
return "UNKNOWN_LIBSWD_OPERATION";
}
/** Helper function that can print name of the request fields.
* \param libswdctx points to the swd context and its necessary to know
DP SELECT register value as it determines CTRL/STAT or WCR access.
* \param RnW is the read/write bit of the request packet.
* \param addr is the address of the register.
* \return char* array with the register name string.
*/
const char *libswd_request_string(libswd_ctx_t *libswdctx, char request){
static char string[100], tmp[8]; string[0]=0;
int apndp=request&LIBSWD_REQUEST_APnDP;
int addr=((request&LIBSWD_REQUEST_A3)?1<<3:0)|((request&LIBSWD_REQUEST_A2)?1<<2:0);
int rnw=request&LIBSWD_REQUEST_RnW;
int parity=request&LIBSWD_REQUEST_PARITY;
strcat(string, apndp?"AccessPort ":"DebugPort ");
strcat(string, rnw?"Read ":"Write ");
strcat(string, "Addr="); sprintf(tmp, "0x%02X", addr); strcat(string, tmp);
if (apndp){
// APnDP=1 so we print out the AHB-AP registers
addr|=libswdctx->log.dp.select&LIBSWD_DP_SELECT_APBANKSEL;
switch (addr){
case 0x00: strcat(string, "(R/W: Control/Status Word, CSW (reset value: 0x43800042)) "); break;
case 0x04: strcat(string, "(R/W: Transfer Address, TAR (reset value: 0x00000000)) "); break;
case 0x08: strcat(string, "(Reserved SBZ) "); break;
case 0x0c: strcat(string, "(R/W, Data Read/Write, DRW) "); break;
case 0x10: strcat(string, "(R/W, Banked Data 0, BD0) "); break;
case 0x14: strcat(string, "(R/W, Banked Data 1, BD1) "); break;
case 0x18: strcat(string, "(R/W, Banked Data 2, BD2 )"); break;
case 0x1c: strcat(string, "(R/W, Banked Data 3, BD3) "); break;
case 0xf8: strcat(string, "(RO, Debug ROM table (reset value: 0xE00FF000)) "); break;
case 0xfc: strcat(string, "(RO, Identification Register, IDR (reset value: 0x24770001)) "); break;
default: strcat(string, "(UNKNOWN) ");
}
} else {
// APnDP=0 so we print out the SW-DP registers
if (rnw) {
switch (addr){
case LIBSWD_DP_IDCODE_ADDR: strcat(string, "(IDCODE)"); break;
case LIBSWD_DP_CTRLSTAT_ADDR: strcat(string, (libswdctx->log.dp.select&1<<LIBSWD_DP_SELECT_CTRLSEL_BITNUM)?"(CTRL/STAT or [WCR])":"([CTRL/STAT] or WCR)"); break;
case LIBSWD_DP_RESEND_ADDR: strcat(string ,"(RESEND) "); break;
case LIBSWD_DP_RDBUFF_ADDR: strcat(string, "(RDBUFF) "); break;
default: strcat(string, "(UNKNOWN) ");
}
} else {
switch (addr) {
case LIBSWD_DP_ABORT_ADDR: strcat(string, "(ABORT) "); break;
case LIBSWD_DP_CTRLSTAT_ADDR: strcat(string, (libswdctx->log.dp.select&1<<LIBSWD_DP_SELECT_CTRLSEL_BITNUM)?"(CTRL/STAT or [WCR]) ":"([CTRL/STAT] or WCR) "); break;
case LIBSWD_DP_SELECT_ADDR: strcat(string, "(SELECT) "); break;
case LIBSWD_DP_ROUTESEL_ADDR: strcat(string, "(ROUTESEL)"); break;
default: strcat(string, "(UNKNOWN) ");
}
}
}
strcat(string, "Parity="); strcat(string, parity?"1":"0");
return string;
}
/** @} */