1*7dc86dfdSMatthias Ringwald /********************************************************************* 2*7dc86dfdSMatthias Ringwald * SEGGER MICROCONTROLLER GmbH & Co. KG * 3*7dc86dfdSMatthias Ringwald * Solutions for real time microcontroller applications * 4*7dc86dfdSMatthias Ringwald ********************************************************************** 5*7dc86dfdSMatthias Ringwald * * 6*7dc86dfdSMatthias Ringwald * (c) 2014 - 2016 SEGGER Microcontroller GmbH & Co. KG * 7*7dc86dfdSMatthias Ringwald * * 8*7dc86dfdSMatthias Ringwald * www.segger.com Support: [email protected] * 9*7dc86dfdSMatthias Ringwald * * 10*7dc86dfdSMatthias Ringwald ********************************************************************** 11*7dc86dfdSMatthias Ringwald * * 12*7dc86dfdSMatthias Ringwald * SEGGER RTT * Real Time Transfer for embedded targets * 13*7dc86dfdSMatthias Ringwald * * 14*7dc86dfdSMatthias Ringwald ********************************************************************** 15*7dc86dfdSMatthias Ringwald * * 16*7dc86dfdSMatthias Ringwald * All rights reserved. * 17*7dc86dfdSMatthias Ringwald * * 18*7dc86dfdSMatthias Ringwald * SEGGER strongly recommends to not make any changes * 19*7dc86dfdSMatthias Ringwald * to or modify the source code of this software in order to stay * 20*7dc86dfdSMatthias Ringwald * compatible with the RTT protocol and J-Link. * 21*7dc86dfdSMatthias Ringwald * * 22*7dc86dfdSMatthias Ringwald * Redistribution and use in source and binary forms, with or * 23*7dc86dfdSMatthias Ringwald * without modification, are permitted provided that the following * 24*7dc86dfdSMatthias Ringwald * conditions are met: * 25*7dc86dfdSMatthias Ringwald * * 26*7dc86dfdSMatthias Ringwald * o Redistributions of source code must retain the above copyright * 27*7dc86dfdSMatthias Ringwald * notice, this list of conditions and the following disclaimer. * 28*7dc86dfdSMatthias Ringwald * * 29*7dc86dfdSMatthias Ringwald * o Redistributions in binary form must reproduce the above * 30*7dc86dfdSMatthias Ringwald * copyright notice, this list of conditions and the following * 31*7dc86dfdSMatthias Ringwald * disclaimer in the documentation and/or other materials provided * 32*7dc86dfdSMatthias Ringwald * with the distribution. * 33*7dc86dfdSMatthias Ringwald * * 34*7dc86dfdSMatthias Ringwald * o Neither the name of SEGGER Microcontroller GmbH & Co. KG * 35*7dc86dfdSMatthias Ringwald * nor the names of its contributors may be used to endorse or * 36*7dc86dfdSMatthias Ringwald * promote products derived from this software without specific * 37*7dc86dfdSMatthias Ringwald * prior written permission. * 38*7dc86dfdSMatthias Ringwald * * 39*7dc86dfdSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 40*7dc86dfdSMatthias Ringwald * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 41*7dc86dfdSMatthias Ringwald * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 42*7dc86dfdSMatthias Ringwald * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 43*7dc86dfdSMatthias Ringwald * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 44*7dc86dfdSMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 45*7dc86dfdSMatthias Ringwald * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 46*7dc86dfdSMatthias Ringwald * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 47*7dc86dfdSMatthias Ringwald * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 48*7dc86dfdSMatthias Ringwald * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 49*7dc86dfdSMatthias Ringwald * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 50*7dc86dfdSMatthias Ringwald * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 51*7dc86dfdSMatthias Ringwald * DAMAGE. * 52*7dc86dfdSMatthias Ringwald * * 53*7dc86dfdSMatthias Ringwald ********************************************************************** 54*7dc86dfdSMatthias Ringwald ---------------------------END-OF-HEADER------------------------------ 55*7dc86dfdSMatthias Ringwald File : SEGGER_RTT_printf.c 56*7dc86dfdSMatthias Ringwald Purpose : Replacement for printf to write formatted data via RTT 57*7dc86dfdSMatthias Ringwald Revision: $Rev: 4351 $ 58*7dc86dfdSMatthias Ringwald ---------------------------------------------------------------------- 59*7dc86dfdSMatthias Ringwald */ 60*7dc86dfdSMatthias Ringwald #include "SEGGER_RTT.h" 61*7dc86dfdSMatthias Ringwald #include "SEGGER_RTT_Conf.h" 62*7dc86dfdSMatthias Ringwald 63*7dc86dfdSMatthias Ringwald /********************************************************************* 64*7dc86dfdSMatthias Ringwald * 65*7dc86dfdSMatthias Ringwald * Defines, configurable 66*7dc86dfdSMatthias Ringwald * 67*7dc86dfdSMatthias Ringwald ********************************************************************** 68*7dc86dfdSMatthias Ringwald */ 69*7dc86dfdSMatthias Ringwald 70*7dc86dfdSMatthias Ringwald #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 71*7dc86dfdSMatthias Ringwald #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) 72*7dc86dfdSMatthias Ringwald #endif 73*7dc86dfdSMatthias Ringwald 74*7dc86dfdSMatthias Ringwald #include <stdlib.h> 75*7dc86dfdSMatthias Ringwald #include <stdarg.h> 76*7dc86dfdSMatthias Ringwald 77*7dc86dfdSMatthias Ringwald 78*7dc86dfdSMatthias Ringwald #define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) 79*7dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PAD_ZERO (1u << 1) 80*7dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PRINT_SIGN (1u << 2) 81*7dc86dfdSMatthias Ringwald #define FORMAT_FLAG_ALTERNATE (1u << 3) 82*7dc86dfdSMatthias Ringwald 83*7dc86dfdSMatthias Ringwald /********************************************************************* 84*7dc86dfdSMatthias Ringwald * 85*7dc86dfdSMatthias Ringwald * Types 86*7dc86dfdSMatthias Ringwald * 87*7dc86dfdSMatthias Ringwald ********************************************************************** 88*7dc86dfdSMatthias Ringwald */ 89*7dc86dfdSMatthias Ringwald 90*7dc86dfdSMatthias Ringwald typedef struct { 91*7dc86dfdSMatthias Ringwald char* pBuffer; 92*7dc86dfdSMatthias Ringwald unsigned BufferSize; 93*7dc86dfdSMatthias Ringwald unsigned Cnt; 94*7dc86dfdSMatthias Ringwald 95*7dc86dfdSMatthias Ringwald int ReturnValue; 96*7dc86dfdSMatthias Ringwald 97*7dc86dfdSMatthias Ringwald unsigned RTTBufferIndex; 98*7dc86dfdSMatthias Ringwald } SEGGER_RTT_PRINTF_DESC; 99*7dc86dfdSMatthias Ringwald 100*7dc86dfdSMatthias Ringwald /********************************************************************* 101*7dc86dfdSMatthias Ringwald * 102*7dc86dfdSMatthias Ringwald * Function prototypes 103*7dc86dfdSMatthias Ringwald * 104*7dc86dfdSMatthias Ringwald ********************************************************************** 105*7dc86dfdSMatthias Ringwald */ 106*7dc86dfdSMatthias Ringwald int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList); 107*7dc86dfdSMatthias Ringwald 108*7dc86dfdSMatthias Ringwald /********************************************************************* 109*7dc86dfdSMatthias Ringwald * 110*7dc86dfdSMatthias Ringwald * Static code 111*7dc86dfdSMatthias Ringwald * 112*7dc86dfdSMatthias Ringwald ********************************************************************** 113*7dc86dfdSMatthias Ringwald */ 114*7dc86dfdSMatthias Ringwald /********************************************************************* 115*7dc86dfdSMatthias Ringwald * 116*7dc86dfdSMatthias Ringwald * _StoreChar 117*7dc86dfdSMatthias Ringwald */ 118*7dc86dfdSMatthias Ringwald static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { 119*7dc86dfdSMatthias Ringwald unsigned Cnt; 120*7dc86dfdSMatthias Ringwald 121*7dc86dfdSMatthias Ringwald Cnt = p->Cnt; 122*7dc86dfdSMatthias Ringwald if ((Cnt + 1u) <= p->BufferSize) { 123*7dc86dfdSMatthias Ringwald *(p->pBuffer + Cnt) = c; 124*7dc86dfdSMatthias Ringwald p->Cnt = Cnt + 1u; 125*7dc86dfdSMatthias Ringwald p->ReturnValue++; 126*7dc86dfdSMatthias Ringwald } 127*7dc86dfdSMatthias Ringwald // 128*7dc86dfdSMatthias Ringwald // Write part of string, when the buffer is full 129*7dc86dfdSMatthias Ringwald // 130*7dc86dfdSMatthias Ringwald if (p->Cnt == p->BufferSize) { 131*7dc86dfdSMatthias Ringwald if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { 132*7dc86dfdSMatthias Ringwald p->ReturnValue = -1; 133*7dc86dfdSMatthias Ringwald } else { 134*7dc86dfdSMatthias Ringwald p->Cnt = 0u; 135*7dc86dfdSMatthias Ringwald } 136*7dc86dfdSMatthias Ringwald } 137*7dc86dfdSMatthias Ringwald } 138*7dc86dfdSMatthias Ringwald 139*7dc86dfdSMatthias Ringwald /********************************************************************* 140*7dc86dfdSMatthias Ringwald * 141*7dc86dfdSMatthias Ringwald * _PrintUnsigned 142*7dc86dfdSMatthias Ringwald */ 143*7dc86dfdSMatthias Ringwald static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 144*7dc86dfdSMatthias Ringwald static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 145*7dc86dfdSMatthias Ringwald unsigned Div; 146*7dc86dfdSMatthias Ringwald unsigned Digit; 147*7dc86dfdSMatthias Ringwald unsigned Number; 148*7dc86dfdSMatthias Ringwald unsigned Width; 149*7dc86dfdSMatthias Ringwald char c; 150*7dc86dfdSMatthias Ringwald 151*7dc86dfdSMatthias Ringwald Number = v; 152*7dc86dfdSMatthias Ringwald Digit = 1u; 153*7dc86dfdSMatthias Ringwald // 154*7dc86dfdSMatthias Ringwald // Get actual field width 155*7dc86dfdSMatthias Ringwald // 156*7dc86dfdSMatthias Ringwald Width = 1u; 157*7dc86dfdSMatthias Ringwald while (Number >= Base) { 158*7dc86dfdSMatthias Ringwald Number = (Number / Base); 159*7dc86dfdSMatthias Ringwald Width++; 160*7dc86dfdSMatthias Ringwald } 161*7dc86dfdSMatthias Ringwald if (NumDigits > Width) { 162*7dc86dfdSMatthias Ringwald Width = NumDigits; 163*7dc86dfdSMatthias Ringwald } 164*7dc86dfdSMatthias Ringwald // 165*7dc86dfdSMatthias Ringwald // Print leading chars if necessary 166*7dc86dfdSMatthias Ringwald // 167*7dc86dfdSMatthias Ringwald if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { 168*7dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 169*7dc86dfdSMatthias Ringwald if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { 170*7dc86dfdSMatthias Ringwald c = '0'; 171*7dc86dfdSMatthias Ringwald } else { 172*7dc86dfdSMatthias Ringwald c = ' '; 173*7dc86dfdSMatthias Ringwald } 174*7dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 175*7dc86dfdSMatthias Ringwald FieldWidth--; 176*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, c); 177*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 178*7dc86dfdSMatthias Ringwald break; 179*7dc86dfdSMatthias Ringwald } 180*7dc86dfdSMatthias Ringwald } 181*7dc86dfdSMatthias Ringwald } 182*7dc86dfdSMatthias Ringwald } 183*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 184*7dc86dfdSMatthias Ringwald // 185*7dc86dfdSMatthias Ringwald // Compute Digit. 186*7dc86dfdSMatthias Ringwald // Loop until Digit has the value of the highest digit required. 187*7dc86dfdSMatthias Ringwald // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. 188*7dc86dfdSMatthias Ringwald // 189*7dc86dfdSMatthias Ringwald while (1) { 190*7dc86dfdSMatthias Ringwald if (NumDigits > 1u) { // User specified a min number of digits to print? => Make sure we loop at least that often, before checking anything else (> 1 check avoids problems with NumDigits being signed / unsigned) 191*7dc86dfdSMatthias Ringwald NumDigits--; 192*7dc86dfdSMatthias Ringwald } else { 193*7dc86dfdSMatthias Ringwald Div = v / Digit; 194*7dc86dfdSMatthias Ringwald if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done 195*7dc86dfdSMatthias Ringwald break; 196*7dc86dfdSMatthias Ringwald } 197*7dc86dfdSMatthias Ringwald } 198*7dc86dfdSMatthias Ringwald Digit *= Base; 199*7dc86dfdSMatthias Ringwald } 200*7dc86dfdSMatthias Ringwald // 201*7dc86dfdSMatthias Ringwald // Output digits 202*7dc86dfdSMatthias Ringwald // 203*7dc86dfdSMatthias Ringwald do { 204*7dc86dfdSMatthias Ringwald Div = v / Digit; 205*7dc86dfdSMatthias Ringwald v -= Div * Digit; 206*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, _aV2C[Div]); 207*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 208*7dc86dfdSMatthias Ringwald break; 209*7dc86dfdSMatthias Ringwald } 210*7dc86dfdSMatthias Ringwald Digit /= Base; 211*7dc86dfdSMatthias Ringwald } while (Digit); 212*7dc86dfdSMatthias Ringwald // 213*7dc86dfdSMatthias Ringwald // Print trailing spaces if necessary 214*7dc86dfdSMatthias Ringwald // 215*7dc86dfdSMatthias Ringwald if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { 216*7dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 217*7dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 218*7dc86dfdSMatthias Ringwald FieldWidth--; 219*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, ' '); 220*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 221*7dc86dfdSMatthias Ringwald break; 222*7dc86dfdSMatthias Ringwald } 223*7dc86dfdSMatthias Ringwald } 224*7dc86dfdSMatthias Ringwald } 225*7dc86dfdSMatthias Ringwald } 226*7dc86dfdSMatthias Ringwald } 227*7dc86dfdSMatthias Ringwald } 228*7dc86dfdSMatthias Ringwald 229*7dc86dfdSMatthias Ringwald /********************************************************************* 230*7dc86dfdSMatthias Ringwald * 231*7dc86dfdSMatthias Ringwald * _PrintInt 232*7dc86dfdSMatthias Ringwald */ 233*7dc86dfdSMatthias Ringwald static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 234*7dc86dfdSMatthias Ringwald unsigned Width; 235*7dc86dfdSMatthias Ringwald int Number; 236*7dc86dfdSMatthias Ringwald 237*7dc86dfdSMatthias Ringwald Number = (v < 0) ? -v : v; 238*7dc86dfdSMatthias Ringwald 239*7dc86dfdSMatthias Ringwald // 240*7dc86dfdSMatthias Ringwald // Get actual field width 241*7dc86dfdSMatthias Ringwald // 242*7dc86dfdSMatthias Ringwald Width = 1u; 243*7dc86dfdSMatthias Ringwald while (Number >= (int)Base) { 244*7dc86dfdSMatthias Ringwald Number = (Number / (int)Base); 245*7dc86dfdSMatthias Ringwald Width++; 246*7dc86dfdSMatthias Ringwald } 247*7dc86dfdSMatthias Ringwald if (NumDigits > Width) { 248*7dc86dfdSMatthias Ringwald Width = NumDigits; 249*7dc86dfdSMatthias Ringwald } 250*7dc86dfdSMatthias Ringwald if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { 251*7dc86dfdSMatthias Ringwald FieldWidth--; 252*7dc86dfdSMatthias Ringwald } 253*7dc86dfdSMatthias Ringwald 254*7dc86dfdSMatthias Ringwald // 255*7dc86dfdSMatthias Ringwald // Print leading spaces if necessary 256*7dc86dfdSMatthias Ringwald // 257*7dc86dfdSMatthias Ringwald if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { 258*7dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 259*7dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 260*7dc86dfdSMatthias Ringwald FieldWidth--; 261*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, ' '); 262*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 263*7dc86dfdSMatthias Ringwald break; 264*7dc86dfdSMatthias Ringwald } 265*7dc86dfdSMatthias Ringwald } 266*7dc86dfdSMatthias Ringwald } 267*7dc86dfdSMatthias Ringwald } 268*7dc86dfdSMatthias Ringwald // 269*7dc86dfdSMatthias Ringwald // Print sign if necessary 270*7dc86dfdSMatthias Ringwald // 271*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 272*7dc86dfdSMatthias Ringwald if (v < 0) { 273*7dc86dfdSMatthias Ringwald v = -v; 274*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '-'); 275*7dc86dfdSMatthias Ringwald } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { 276*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '+'); 277*7dc86dfdSMatthias Ringwald } else { 278*7dc86dfdSMatthias Ringwald 279*7dc86dfdSMatthias Ringwald } 280*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 281*7dc86dfdSMatthias Ringwald // 282*7dc86dfdSMatthias Ringwald // Print leading zeros if necessary 283*7dc86dfdSMatthias Ringwald // 284*7dc86dfdSMatthias Ringwald if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { 285*7dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 286*7dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 287*7dc86dfdSMatthias Ringwald FieldWidth--; 288*7dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '0'); 289*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 290*7dc86dfdSMatthias Ringwald break; 291*7dc86dfdSMatthias Ringwald } 292*7dc86dfdSMatthias Ringwald } 293*7dc86dfdSMatthias Ringwald } 294*7dc86dfdSMatthias Ringwald } 295*7dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 296*7dc86dfdSMatthias Ringwald // 297*7dc86dfdSMatthias Ringwald // Print number without sign 298*7dc86dfdSMatthias Ringwald // 299*7dc86dfdSMatthias Ringwald _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); 300*7dc86dfdSMatthias Ringwald } 301*7dc86dfdSMatthias Ringwald } 302*7dc86dfdSMatthias Ringwald } 303*7dc86dfdSMatthias Ringwald } 304*7dc86dfdSMatthias Ringwald 305*7dc86dfdSMatthias Ringwald /********************************************************************* 306*7dc86dfdSMatthias Ringwald * 307*7dc86dfdSMatthias Ringwald * Public code 308*7dc86dfdSMatthias Ringwald * 309*7dc86dfdSMatthias Ringwald ********************************************************************** 310*7dc86dfdSMatthias Ringwald */ 311*7dc86dfdSMatthias Ringwald /********************************************************************* 312*7dc86dfdSMatthias Ringwald * 313*7dc86dfdSMatthias Ringwald * SEGGER_RTT_vprintf 314*7dc86dfdSMatthias Ringwald * 315*7dc86dfdSMatthias Ringwald * Function description 316*7dc86dfdSMatthias Ringwald * Stores a formatted string in SEGGER RTT control block. 317*7dc86dfdSMatthias Ringwald * This data is read by the host. 318*7dc86dfdSMatthias Ringwald * 319*7dc86dfdSMatthias Ringwald * Parameters 320*7dc86dfdSMatthias Ringwald * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 321*7dc86dfdSMatthias Ringwald * sFormat Pointer to format string 322*7dc86dfdSMatthias Ringwald * pParamList Pointer to the list of arguments for the format string 323*7dc86dfdSMatthias Ringwald * 324*7dc86dfdSMatthias Ringwald * Return values 325*7dc86dfdSMatthias Ringwald * >= 0: Number of bytes which have been stored in the "Up"-buffer. 326*7dc86dfdSMatthias Ringwald * < 0: Error 327*7dc86dfdSMatthias Ringwald */ 328*7dc86dfdSMatthias Ringwald int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { 329*7dc86dfdSMatthias Ringwald char c; 330*7dc86dfdSMatthias Ringwald SEGGER_RTT_PRINTF_DESC BufferDesc; 331*7dc86dfdSMatthias Ringwald int v; 332*7dc86dfdSMatthias Ringwald unsigned NumDigits; 333*7dc86dfdSMatthias Ringwald unsigned FormatFlags; 334*7dc86dfdSMatthias Ringwald unsigned FieldWidth; 335*7dc86dfdSMatthias Ringwald char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; 336*7dc86dfdSMatthias Ringwald 337*7dc86dfdSMatthias Ringwald BufferDesc.pBuffer = acBuffer; 338*7dc86dfdSMatthias Ringwald BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; 339*7dc86dfdSMatthias Ringwald BufferDesc.Cnt = 0u; 340*7dc86dfdSMatthias Ringwald BufferDesc.RTTBufferIndex = BufferIndex; 341*7dc86dfdSMatthias Ringwald BufferDesc.ReturnValue = 0; 342*7dc86dfdSMatthias Ringwald 343*7dc86dfdSMatthias Ringwald do { 344*7dc86dfdSMatthias Ringwald c = *sFormat; 345*7dc86dfdSMatthias Ringwald sFormat++; 346*7dc86dfdSMatthias Ringwald if (c == 0u) { 347*7dc86dfdSMatthias Ringwald break; 348*7dc86dfdSMatthias Ringwald } 349*7dc86dfdSMatthias Ringwald if (c == '%') { 350*7dc86dfdSMatthias Ringwald // 351*7dc86dfdSMatthias Ringwald // Filter out flags 352*7dc86dfdSMatthias Ringwald // 353*7dc86dfdSMatthias Ringwald FormatFlags = 0u; 354*7dc86dfdSMatthias Ringwald v = 1; 355*7dc86dfdSMatthias Ringwald do { 356*7dc86dfdSMatthias Ringwald c = *sFormat; 357*7dc86dfdSMatthias Ringwald switch (c) { 358*7dc86dfdSMatthias Ringwald case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; 359*7dc86dfdSMatthias Ringwald case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; 360*7dc86dfdSMatthias Ringwald case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; 361*7dc86dfdSMatthias Ringwald case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; 362*7dc86dfdSMatthias Ringwald default: v = 0; break; 363*7dc86dfdSMatthias Ringwald } 364*7dc86dfdSMatthias Ringwald } while (v); 365*7dc86dfdSMatthias Ringwald // 366*7dc86dfdSMatthias Ringwald // filter out field with 367*7dc86dfdSMatthias Ringwald // 368*7dc86dfdSMatthias Ringwald FieldWidth = 0u; 369*7dc86dfdSMatthias Ringwald do { 370*7dc86dfdSMatthias Ringwald c = *sFormat; 371*7dc86dfdSMatthias Ringwald if ((c < '0') || (c > '9')) { 372*7dc86dfdSMatthias Ringwald break; 373*7dc86dfdSMatthias Ringwald } 374*7dc86dfdSMatthias Ringwald sFormat++; 375*7dc86dfdSMatthias Ringwald FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); 376*7dc86dfdSMatthias Ringwald } while (1); 377*7dc86dfdSMatthias Ringwald 378*7dc86dfdSMatthias Ringwald // 379*7dc86dfdSMatthias Ringwald // Filter out precision (number of digits to display) 380*7dc86dfdSMatthias Ringwald // 381*7dc86dfdSMatthias Ringwald NumDigits = 0u; 382*7dc86dfdSMatthias Ringwald c = *sFormat; 383*7dc86dfdSMatthias Ringwald if (c == '.') { 384*7dc86dfdSMatthias Ringwald sFormat++; 385*7dc86dfdSMatthias Ringwald do { 386*7dc86dfdSMatthias Ringwald c = *sFormat; 387*7dc86dfdSMatthias Ringwald if ((c < '0') || (c > '9')) { 388*7dc86dfdSMatthias Ringwald break; 389*7dc86dfdSMatthias Ringwald } 390*7dc86dfdSMatthias Ringwald sFormat++; 391*7dc86dfdSMatthias Ringwald NumDigits = NumDigits * 10u + ((unsigned)c - '0'); 392*7dc86dfdSMatthias Ringwald } while (1); 393*7dc86dfdSMatthias Ringwald } 394*7dc86dfdSMatthias Ringwald // 395*7dc86dfdSMatthias Ringwald // Filter out length modifier 396*7dc86dfdSMatthias Ringwald // 397*7dc86dfdSMatthias Ringwald c = *sFormat; 398*7dc86dfdSMatthias Ringwald do { 399*7dc86dfdSMatthias Ringwald if ((c == 'l') || (c == 'h')) { 400*7dc86dfdSMatthias Ringwald sFormat++; 401*7dc86dfdSMatthias Ringwald c = *sFormat; 402*7dc86dfdSMatthias Ringwald } else { 403*7dc86dfdSMatthias Ringwald break; 404*7dc86dfdSMatthias Ringwald } 405*7dc86dfdSMatthias Ringwald } while (1); 406*7dc86dfdSMatthias Ringwald // 407*7dc86dfdSMatthias Ringwald // Handle specifiers 408*7dc86dfdSMatthias Ringwald // 409*7dc86dfdSMatthias Ringwald switch (c) { 410*7dc86dfdSMatthias Ringwald case 'c': { 411*7dc86dfdSMatthias Ringwald char c0; 412*7dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 413*7dc86dfdSMatthias Ringwald c0 = (char)v; 414*7dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c0); 415*7dc86dfdSMatthias Ringwald break; 416*7dc86dfdSMatthias Ringwald } 417*7dc86dfdSMatthias Ringwald case 'd': 418*7dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 419*7dc86dfdSMatthias Ringwald _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); 420*7dc86dfdSMatthias Ringwald break; 421*7dc86dfdSMatthias Ringwald case 'u': 422*7dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 423*7dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); 424*7dc86dfdSMatthias Ringwald break; 425*7dc86dfdSMatthias Ringwald case 'x': 426*7dc86dfdSMatthias Ringwald case 'X': 427*7dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 428*7dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); 429*7dc86dfdSMatthias Ringwald break; 430*7dc86dfdSMatthias Ringwald case 's': 431*7dc86dfdSMatthias Ringwald { 432*7dc86dfdSMatthias Ringwald const char * s = va_arg(*pParamList, const char *); 433*7dc86dfdSMatthias Ringwald do { 434*7dc86dfdSMatthias Ringwald c = *s; 435*7dc86dfdSMatthias Ringwald s++; 436*7dc86dfdSMatthias Ringwald if (c == '\0') { 437*7dc86dfdSMatthias Ringwald break; 438*7dc86dfdSMatthias Ringwald } 439*7dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c); 440*7dc86dfdSMatthias Ringwald } while (BufferDesc.ReturnValue >= 0); 441*7dc86dfdSMatthias Ringwald } 442*7dc86dfdSMatthias Ringwald break; 443*7dc86dfdSMatthias Ringwald case 'p': 444*7dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 445*7dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); 446*7dc86dfdSMatthias Ringwald break; 447*7dc86dfdSMatthias Ringwald case '%': 448*7dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, '%'); 449*7dc86dfdSMatthias Ringwald break; 450*7dc86dfdSMatthias Ringwald default: 451*7dc86dfdSMatthias Ringwald break; 452*7dc86dfdSMatthias Ringwald } 453*7dc86dfdSMatthias Ringwald sFormat++; 454*7dc86dfdSMatthias Ringwald } else { 455*7dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c); 456*7dc86dfdSMatthias Ringwald } 457*7dc86dfdSMatthias Ringwald } while (BufferDesc.ReturnValue >= 0); 458*7dc86dfdSMatthias Ringwald 459*7dc86dfdSMatthias Ringwald if (BufferDesc.ReturnValue > 0) { 460*7dc86dfdSMatthias Ringwald // 461*7dc86dfdSMatthias Ringwald // Write remaining data, if any 462*7dc86dfdSMatthias Ringwald // 463*7dc86dfdSMatthias Ringwald if (BufferDesc.Cnt != 0u) { 464*7dc86dfdSMatthias Ringwald SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); 465*7dc86dfdSMatthias Ringwald } 466*7dc86dfdSMatthias Ringwald BufferDesc.ReturnValue += (int)BufferDesc.Cnt; 467*7dc86dfdSMatthias Ringwald } 468*7dc86dfdSMatthias Ringwald return BufferDesc.ReturnValue; 469*7dc86dfdSMatthias Ringwald } 470*7dc86dfdSMatthias Ringwald 471*7dc86dfdSMatthias Ringwald /********************************************************************* 472*7dc86dfdSMatthias Ringwald * 473*7dc86dfdSMatthias Ringwald * SEGGER_RTT_printf 474*7dc86dfdSMatthias Ringwald * 475*7dc86dfdSMatthias Ringwald * Function description 476*7dc86dfdSMatthias Ringwald * Stores a formatted string in SEGGER RTT control block. 477*7dc86dfdSMatthias Ringwald * This data is read by the host. 478*7dc86dfdSMatthias Ringwald * 479*7dc86dfdSMatthias Ringwald * Parameters 480*7dc86dfdSMatthias Ringwald * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 481*7dc86dfdSMatthias Ringwald * sFormat Pointer to format string, followed by the arguments for conversion 482*7dc86dfdSMatthias Ringwald * 483*7dc86dfdSMatthias Ringwald * Return values 484*7dc86dfdSMatthias Ringwald * >= 0: Number of bytes which have been stored in the "Up"-buffer. 485*7dc86dfdSMatthias Ringwald * < 0: Error 486*7dc86dfdSMatthias Ringwald * 487*7dc86dfdSMatthias Ringwald * Notes 488*7dc86dfdSMatthias Ringwald * (1) Conversion specifications have following syntax: 489*7dc86dfdSMatthias Ringwald * %[flags][FieldWidth][.Precision]ConversionSpecifier 490*7dc86dfdSMatthias Ringwald * (2) Supported flags: 491*7dc86dfdSMatthias Ringwald * -: Left justify within the field width 492*7dc86dfdSMatthias Ringwald * +: Always print sign extension for signed conversions 493*7dc86dfdSMatthias Ringwald * 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision 494*7dc86dfdSMatthias Ringwald * Supported conversion specifiers: 495*7dc86dfdSMatthias Ringwald * c: Print the argument as one char 496*7dc86dfdSMatthias Ringwald * d: Print the argument as a signed integer 497*7dc86dfdSMatthias Ringwald * u: Print the argument as an unsigned integer 498*7dc86dfdSMatthias Ringwald * x: Print the argument as an hexadecimal integer 499*7dc86dfdSMatthias Ringwald * s: Print the string pointed to by the argument 500*7dc86dfdSMatthias Ringwald * p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) 501*7dc86dfdSMatthias Ringwald */ 502*7dc86dfdSMatthias Ringwald int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { 503*7dc86dfdSMatthias Ringwald int r; 504*7dc86dfdSMatthias Ringwald va_list ParamList; 505*7dc86dfdSMatthias Ringwald 506*7dc86dfdSMatthias Ringwald va_start(ParamList, sFormat); 507*7dc86dfdSMatthias Ringwald r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); 508*7dc86dfdSMatthias Ringwald va_end(ParamList); 509*7dc86dfdSMatthias Ringwald return r; 510*7dc86dfdSMatthias Ringwald } 511*7dc86dfdSMatthias Ringwald /*************************** End of file ****************************/ 512