README(.md) update and reformat to fit GitHub.
[libswd.git] / src / libswd_log.c
blob0fab869a3eed97c20f101f0a117b6d790dbf0e88
1 /*
2 * Serial Wire Debug Open Library.
3 * Library Body File.
5 * Copyright (C) 2010-2013, Tomasz Boleslaw CEDRO (http://www.tomek.cedro.info)
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
15 * 3. Neither the name of the Tomasz Boleslaw CEDRO nor the names of its
16 * contributors may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
27 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
29 * OF THE POSSIBILITY OF SUCH DAMAGE.*
31 * Written by Tomasz Boleslaw CEDRO <cederom@tlen.pl>, 2010-2013;
35 /** \file libswd_log.c */
37 #include <libswd.h>
39 /*******************************************************************************
40 * \defgroup libswd_log Miscelanous logging functionalities.
41 * @{
42 ******************************************************************************/
44 /** Logging functionality can be external or internal, by default external
45 * function can be defined to use target program logging mechanism.
46 * To use internal logging mechanism simply wrap libswd_log_internal() around
47 * this function in application specific driver bridge file,
48 * see liblibswd_externs.c for examples. When you want to use variable argument
49 * (printf style) invocation you can use libswd_log_internal_va() as vprintf().
51 extern int libswd_log(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel, char *msg, ...);
53 /** Put a message into swd context log at specified verbosity level.
54 * If specified message's log level is lower than actual context configuration,
55 * message will be omitted. Verbosity level increases from 0 (silent) to 6 (bitstream).
56 * This function does not put '\n' at the end of line so you need to put them by hand.
57 * \param *libswdctx swd context.
58 * \param loglevel at which to put selected message.
59 * \param *msg message body with variable arguments as in "printf".
60 * \return number of characters written or error code on failure.
62 int libswd_log_internal(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel, char *msg, ...){
63 if (loglevel<LIBSWD_LOGLEVEL_MIN || loglevel>LIBSWD_LOGLEVEL_MAX)
64 return LIBSWD_ERROR_LOGLEVEL;
65 if (loglevel > libswdctx->config.loglevel) return LIBSWD_OK;
66 int res;
67 va_list ap;
68 va_start(ap, msg);
69 res=vprintf(msg, ap);
70 va_end(ap);
71 return res;
74 /** Put a fmt+va_list message into swd context log at specified verbosity level.
75 * It works just as libswd_log_internal() but is intended for use instead
76 * vprintf() between va_start() and va_end()...
77 * \param *libswdctx swd context.
78 * \param loglevel at which to put selected message.
79 * \param *msg message body with variable arguments as in "printf".
80 * \return number of characters written or error code on failure.
82 int libswd_log_internal_va(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel, char *fmt, va_list ap){
83 if (loglevel<LIBSWD_LOGLEVEL_MIN || loglevel>LIBSWD_LOGLEVEL_MAX)
84 return LIBSWD_ERROR_LOGLEVEL;
85 if (loglevel > libswdctx->config.loglevel) return LIBSWD_OK;
86 int res;
87 res=vprintf(fmt, ap);
88 return res;
91 /** Change log level to increase or decrease verbosity level.
92 * \param *libswdctx swd context.
93 * \param loglevel is the target verbosity level to be set.
94 * \return LIBSWD_OK on success or error code.
96 int libswd_log_level_set(libswd_ctx_t *libswdctx, libswd_loglevel_t loglevel){
97 if (libswdctx==NULL) return LIBSWD_ERROR_NULLCONTEXT;
98 if (loglevel<LIBSWD_LOGLEVEL_MIN || loglevel>LIBSWD_LOGLEVEL_MAX)
99 return LIBSWD_ERROR_LOGLEVEL;
101 libswdctx->config.loglevel=loglevel;
102 libswd_log(libswdctx, LIBSWD_LOGLEVEL_DEBUG, "LIBSWD_D: libswd_log_level_set(libswdctx=0x%p, loglevel[%d..%d]=%d/%s)\n", (void*)libswdctx, LIBSWD_LOGLEVEL_MIN, LIBSWD_LOGLEVEL_MAX, loglevel, libswd_log_level_string(loglevel));
103 return LIBSWD_OK;
106 /** Return integer log level value.
107 * \param *libswdctx swd context.
108 * \return integer log level value or LIBSWD_ERROR code on failure.
110 int libswd_log_level_get(libswd_ctx_t *libswdctx){
111 if (libswdctx==NULL) return LIBSWD_ERROR_NULLCONTEXT;
112 return libswdctx->config.loglevel;
115 /** Helper function that returns loglevel name string for logging purposes.
116 * \param loglevel is the libswd_loglevel_t code to produce a string.
117 * \return char* loglevel name sring array.
119 const char *libswd_log_level_string(libswd_loglevel_t loglevel){
120 switch (loglevel){
121 case LIBSWD_LOGLEVEL_SILENT: return "LIBSWD_LOGLEVEL_SILENT";
122 case LIBSWD_LOGLEVEL_ERROR: return "LIBSWD_LOGLEVEL_ERROR";
123 case LIBSWD_LOGLEVEL_WARNING: return "LIBSWD_LOGLEVEL_WARNING";
124 case LIBSWD_LOGLEVEL_NORMAL: return "LIBSWD_LOGLEVEL_NORMAL";
125 case LIBSWD_LOGLEVEL_INFO: return "LIBSWD_LOGLEVEL_INFO";
126 case LIBSWD_LOGLEVEL_DEBUG: return "LIBSWD_LOGLEVEL_DEBUG";
127 case LIBSWD_LOGLEVEL_PAYLOAD: return "LIBSWD_LOGLEVEL_PAYLOAD";
129 return "UNKNOWN_LOGLEVEL";
132 /** Helper function to produce operation name string for logging purposes.
133 * \param operation is the libswd_operation_t code to return as string.
134 * \return char* array with operation name string.
136 const char *libswd_operation_string(libswd_operation_t operation){
137 switch(operation){
138 case LIBSWD_OPERATION_ENQUEUE: return "LIBSWD_OPERATION_ENQUEUE";
139 case LIBSWD_OPERATION_EXECUTE: return "LIBSWD_OPERATION_EXECUTE";
140 case LIBSWD_OPERATION_TRANSMIT_HEAD: return "LIBSWD_OPERATION_TRANSMIT_HEAD";
141 case LIBSWD_OPERATION_TRANSMIT_TAIL: return "LIBSWD_OPERATION_TRANSMIT_TAIL";
142 case LIBSWD_OPERATION_TRANSMIT_ALL: return "LIBSWD_OPERATION_TRANSMIT_ALL";
143 case LIBSWD_OPERATION_TRANSMIT_ONE: return "LIBSWD_OPERATION_TRANSMIT_ONE";
144 case LIBSWD_OPERATION_TRANSMIT_LAST: return "LIBSWD_OPERATION_TRANSMIT_LAST";
146 return "UNKNOWN_LIBSWD_OPERATION";
149 /** Helper function that can print name of the request fields.
150 * DP SELECT APBANKSEL fields are also taken into account here for APACC.
151 * \param libswdctx points to the swd context and its necessary to know
152 DP SELECT register value as it determines CTRL/STAT or WCR access.
153 * \param RnW is the read/write bit of the request packet.
154 * \param addr is the address of the register.
155 * \return char* array with the register name string.
157 const char *libswd_request_string(libswd_ctx_t *libswdctx, char request){
158 static char string[100], tmp[8]; string[0]=0;
159 int apndp=request&LIBSWD_REQUEST_APnDP;
160 int addr=0;
161 addr|=((request&LIBSWD_REQUEST_A3)?1<<3:0);
162 addr|=((request&LIBSWD_REQUEST_A2)?1<<2:0);
163 if (apndp) addr|=(libswdctx->log.dp.select&LIBSWD_DP_SELECT_APBANKSEL);
164 int rnw=request&LIBSWD_REQUEST_RnW;
165 int parity=request&LIBSWD_REQUEST_PARITY;
167 strcat(string, apndp?"AccessPort ":"DebugPort ");
168 strcat(string, rnw?"Read ":"Write ");
169 strcat(string, "Addr="); sprintf(tmp, "0x%02X", addr); strcat(string, tmp);
171 if (apndp){
172 // APnDP=1 so we print out the AHB-AP registers
173 addr|=libswdctx->log.dp.select&LIBSWD_DP_SELECT_APBANKSEL;
174 switch (addr){
175 case 0x00: strcat(string, "(R/W: Control/Status Word, CSW (reset value: 0x43800042)) "); break;
176 case 0x04: strcat(string, "(R/W: Transfer Address, TAR (reset value: 0x00000000)) "); break;
177 case 0x08: strcat(string, "(Reserved SBZ) "); break;
178 case 0x0c: strcat(string, "(R/W, Data Read/Write, DRW) "); break;
179 case 0x10: strcat(string, "(R/W, Banked Data 0, BD0) "); break;
180 case 0x14: strcat(string, "(R/W, Banked Data 1, BD1) "); break;
181 case 0x18: strcat(string, "(R/W, Banked Data 2, BD2 )"); break;
182 case 0x1c: strcat(string, "(R/W, Banked Data 3, BD3) "); break;
183 case 0xf8: strcat(string, "(RO, Debug ROM table (reset value: 0xE00FF000)) "); break;
184 case 0xfc: strcat(string, "(RO, Identification Register, IDR (reset value: 0x24770001)) "); break;
185 default: strcat(string, "(UNKNOWN) ");
187 } else {
188 // APnDP=0 so we print out the SW-DP registers
189 if (rnw) {
190 switch (addr){
191 case LIBSWD_DP_IDCODE_ADDR: strcat(string, "(IDCODE)"); break;
192 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;
193 case LIBSWD_DP_RESEND_ADDR: strcat(string ,"(RESEND) "); break;
194 case LIBSWD_DP_RDBUFF_ADDR: strcat(string, "(RDBUFF) "); break;
195 default: strcat(string, "(UNKNOWN) ");
197 } else {
198 switch (addr) {
199 case LIBSWD_DP_ABORT_ADDR: strcat(string, "(ABORT) "); break;
200 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;
201 case LIBSWD_DP_SELECT_ADDR: strcat(string, "(SELECT) "); break;
202 case LIBSWD_DP_ROUTESEL_ADDR: strcat(string, "(ROUTESEL)"); break;
203 default: strcat(string, "(UNKNOWN) ");
207 strcat(string, "Parity="); strcat(string, parity?"1":"0");
208 return string;
212 /** @} */