17dc86dfdSMatthias Ringwald /********************************************************************* 2*779af47bSMatthias Ringwald * SEGGER Microcontroller GmbH * 37dc86dfdSMatthias Ringwald * Solutions for real time microcontroller applications * 47dc86dfdSMatthias Ringwald ********************************************************************** 57dc86dfdSMatthias Ringwald * * 6*779af47bSMatthias Ringwald * (c) 1995 - 2018 SEGGER Microcontroller GmbH * 77dc86dfdSMatthias Ringwald * * 87dc86dfdSMatthias Ringwald * www.segger.com Support: [email protected] * 97dc86dfdSMatthias Ringwald * * 107dc86dfdSMatthias Ringwald ********************************************************************** 117dc86dfdSMatthias Ringwald * * 127dc86dfdSMatthias Ringwald * SEGGER RTT * Real Time Transfer for embedded targets * 137dc86dfdSMatthias Ringwald * * 147dc86dfdSMatthias Ringwald ********************************************************************** 157dc86dfdSMatthias Ringwald * * 167dc86dfdSMatthias Ringwald * All rights reserved. * 177dc86dfdSMatthias Ringwald * * 187dc86dfdSMatthias Ringwald * SEGGER strongly recommends to not make any changes * 197dc86dfdSMatthias Ringwald * to or modify the source code of this software in order to stay * 207dc86dfdSMatthias Ringwald * compatible with the RTT protocol and J-Link. * 217dc86dfdSMatthias Ringwald * * 227dc86dfdSMatthias Ringwald * Redistribution and use in source and binary forms, with or * 237dc86dfdSMatthias Ringwald * without modification, are permitted provided that the following * 247dc86dfdSMatthias Ringwald * conditions are met: * 257dc86dfdSMatthias Ringwald * * 267dc86dfdSMatthias Ringwald * o Redistributions of source code must retain the above copyright * 277dc86dfdSMatthias Ringwald * notice, this list of conditions and the following disclaimer. * 287dc86dfdSMatthias Ringwald * * 297dc86dfdSMatthias Ringwald * o Redistributions in binary form must reproduce the above * 307dc86dfdSMatthias Ringwald * copyright notice, this list of conditions and the following * 317dc86dfdSMatthias Ringwald * disclaimer in the documentation and/or other materials provided * 327dc86dfdSMatthias Ringwald * with the distribution. * 337dc86dfdSMatthias Ringwald * * 34*779af47bSMatthias Ringwald * o Neither the name of SEGGER Microcontroller GmbH * 357dc86dfdSMatthias Ringwald * nor the names of its contributors may be used to endorse or * 367dc86dfdSMatthias Ringwald * promote products derived from this software without specific * 377dc86dfdSMatthias Ringwald * prior written permission. * 387dc86dfdSMatthias Ringwald * * 397dc86dfdSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * 407dc86dfdSMatthias Ringwald * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, * 417dc86dfdSMatthias Ringwald * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * 427dc86dfdSMatthias Ringwald * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * 437dc86dfdSMatthias Ringwald * DISCLAIMED. IN NO EVENT SHALL SEGGER Microcontroller BE LIABLE FOR * 447dc86dfdSMatthias Ringwald * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * 457dc86dfdSMatthias Ringwald * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * 467dc86dfdSMatthias Ringwald * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * 477dc86dfdSMatthias Ringwald * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * 487dc86dfdSMatthias Ringwald * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * 497dc86dfdSMatthias Ringwald * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE * 507dc86dfdSMatthias Ringwald * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH * 517dc86dfdSMatthias Ringwald * DAMAGE. * 527dc86dfdSMatthias Ringwald * * 537dc86dfdSMatthias Ringwald ********************************************************************** 547dc86dfdSMatthias Ringwald ---------------------------END-OF-HEADER------------------------------ 557dc86dfdSMatthias Ringwald File : SEGGER_RTT_printf.c 567dc86dfdSMatthias Ringwald Purpose : Replacement for printf to write formatted data via RTT 57*779af47bSMatthias Ringwald Revision: $Rev: 12360 $ 587dc86dfdSMatthias Ringwald ---------------------------------------------------------------------- 597dc86dfdSMatthias Ringwald */ 607dc86dfdSMatthias Ringwald #include "SEGGER_RTT.h" 617dc86dfdSMatthias Ringwald #include "SEGGER_RTT_Conf.h" 627dc86dfdSMatthias Ringwald 637dc86dfdSMatthias Ringwald /********************************************************************* 647dc86dfdSMatthias Ringwald * 657dc86dfdSMatthias Ringwald * Defines, configurable 667dc86dfdSMatthias Ringwald * 677dc86dfdSMatthias Ringwald ********************************************************************** 687dc86dfdSMatthias Ringwald */ 697dc86dfdSMatthias Ringwald 707dc86dfdSMatthias Ringwald #ifndef SEGGER_RTT_PRINTF_BUFFER_SIZE 717dc86dfdSMatthias Ringwald #define SEGGER_RTT_PRINTF_BUFFER_SIZE (64) 727dc86dfdSMatthias Ringwald #endif 737dc86dfdSMatthias Ringwald 747dc86dfdSMatthias Ringwald #include <stdlib.h> 757dc86dfdSMatthias Ringwald #include <stdarg.h> 767dc86dfdSMatthias Ringwald 777dc86dfdSMatthias Ringwald 787dc86dfdSMatthias Ringwald #define FORMAT_FLAG_LEFT_JUSTIFY (1u << 0) 797dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PAD_ZERO (1u << 1) 807dc86dfdSMatthias Ringwald #define FORMAT_FLAG_PRINT_SIGN (1u << 2) 817dc86dfdSMatthias Ringwald #define FORMAT_FLAG_ALTERNATE (1u << 3) 827dc86dfdSMatthias Ringwald 837dc86dfdSMatthias Ringwald /********************************************************************* 847dc86dfdSMatthias Ringwald * 857dc86dfdSMatthias Ringwald * Types 867dc86dfdSMatthias Ringwald * 877dc86dfdSMatthias Ringwald ********************************************************************** 887dc86dfdSMatthias Ringwald */ 897dc86dfdSMatthias Ringwald 907dc86dfdSMatthias Ringwald typedef struct { 917dc86dfdSMatthias Ringwald char* pBuffer; 927dc86dfdSMatthias Ringwald unsigned BufferSize; 937dc86dfdSMatthias Ringwald unsigned Cnt; 947dc86dfdSMatthias Ringwald 957dc86dfdSMatthias Ringwald int ReturnValue; 967dc86dfdSMatthias Ringwald 977dc86dfdSMatthias Ringwald unsigned RTTBufferIndex; 987dc86dfdSMatthias Ringwald } SEGGER_RTT_PRINTF_DESC; 997dc86dfdSMatthias Ringwald 1007dc86dfdSMatthias Ringwald /********************************************************************* 1017dc86dfdSMatthias Ringwald * 1027dc86dfdSMatthias Ringwald * Function prototypes 1037dc86dfdSMatthias Ringwald * 1047dc86dfdSMatthias Ringwald ********************************************************************** 1057dc86dfdSMatthias Ringwald */ 1067dc86dfdSMatthias Ringwald 1077dc86dfdSMatthias Ringwald /********************************************************************* 1087dc86dfdSMatthias Ringwald * 1097dc86dfdSMatthias Ringwald * Static code 1107dc86dfdSMatthias Ringwald * 1117dc86dfdSMatthias Ringwald ********************************************************************** 1127dc86dfdSMatthias Ringwald */ 1137dc86dfdSMatthias Ringwald /********************************************************************* 1147dc86dfdSMatthias Ringwald * 1157dc86dfdSMatthias Ringwald * _StoreChar 1167dc86dfdSMatthias Ringwald */ 1177dc86dfdSMatthias Ringwald static void _StoreChar(SEGGER_RTT_PRINTF_DESC * p, char c) { 1187dc86dfdSMatthias Ringwald unsigned Cnt; 1197dc86dfdSMatthias Ringwald 1207dc86dfdSMatthias Ringwald Cnt = p->Cnt; 1217dc86dfdSMatthias Ringwald if ((Cnt + 1u) <= p->BufferSize) { 1227dc86dfdSMatthias Ringwald *(p->pBuffer + Cnt) = c; 1237dc86dfdSMatthias Ringwald p->Cnt = Cnt + 1u; 1247dc86dfdSMatthias Ringwald p->ReturnValue++; 1257dc86dfdSMatthias Ringwald } 1267dc86dfdSMatthias Ringwald // 1277dc86dfdSMatthias Ringwald // Write part of string, when the buffer is full 1287dc86dfdSMatthias Ringwald // 1297dc86dfdSMatthias Ringwald if (p->Cnt == p->BufferSize) { 1307dc86dfdSMatthias Ringwald if (SEGGER_RTT_Write(p->RTTBufferIndex, p->pBuffer, p->Cnt) != p->Cnt) { 1317dc86dfdSMatthias Ringwald p->ReturnValue = -1; 1327dc86dfdSMatthias Ringwald } else { 1337dc86dfdSMatthias Ringwald p->Cnt = 0u; 1347dc86dfdSMatthias Ringwald } 1357dc86dfdSMatthias Ringwald } 1367dc86dfdSMatthias Ringwald } 1377dc86dfdSMatthias Ringwald 1387dc86dfdSMatthias Ringwald /********************************************************************* 1397dc86dfdSMatthias Ringwald * 1407dc86dfdSMatthias Ringwald * _PrintUnsigned 1417dc86dfdSMatthias Ringwald */ 1427dc86dfdSMatthias Ringwald static void _PrintUnsigned(SEGGER_RTT_PRINTF_DESC * pBufferDesc, unsigned v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 1437dc86dfdSMatthias Ringwald static const char _aV2C[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 1447dc86dfdSMatthias Ringwald unsigned Div; 1457dc86dfdSMatthias Ringwald unsigned Digit; 1467dc86dfdSMatthias Ringwald unsigned Number; 1477dc86dfdSMatthias Ringwald unsigned Width; 1487dc86dfdSMatthias Ringwald char c; 1497dc86dfdSMatthias Ringwald 1507dc86dfdSMatthias Ringwald Number = v; 1517dc86dfdSMatthias Ringwald Digit = 1u; 1527dc86dfdSMatthias Ringwald // 1537dc86dfdSMatthias Ringwald // Get actual field width 1547dc86dfdSMatthias Ringwald // 1557dc86dfdSMatthias Ringwald Width = 1u; 1567dc86dfdSMatthias Ringwald while (Number >= Base) { 1577dc86dfdSMatthias Ringwald Number = (Number / Base); 1587dc86dfdSMatthias Ringwald Width++; 1597dc86dfdSMatthias Ringwald } 1607dc86dfdSMatthias Ringwald if (NumDigits > Width) { 1617dc86dfdSMatthias Ringwald Width = NumDigits; 1627dc86dfdSMatthias Ringwald } 1637dc86dfdSMatthias Ringwald // 1647dc86dfdSMatthias Ringwald // Print leading chars if necessary 1657dc86dfdSMatthias Ringwald // 1667dc86dfdSMatthias Ringwald if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) { 1677dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 1687dc86dfdSMatthias Ringwald if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && (NumDigits == 0u)) { 1697dc86dfdSMatthias Ringwald c = '0'; 1707dc86dfdSMatthias Ringwald } else { 1717dc86dfdSMatthias Ringwald c = ' '; 1727dc86dfdSMatthias Ringwald } 1737dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 1747dc86dfdSMatthias Ringwald FieldWidth--; 1757dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, c); 1767dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 1777dc86dfdSMatthias Ringwald break; 1787dc86dfdSMatthias Ringwald } 1797dc86dfdSMatthias Ringwald } 1807dc86dfdSMatthias Ringwald } 1817dc86dfdSMatthias Ringwald } 1827dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 1837dc86dfdSMatthias Ringwald // 1847dc86dfdSMatthias Ringwald // Compute Digit. 1857dc86dfdSMatthias Ringwald // Loop until Digit has the value of the highest digit required. 1867dc86dfdSMatthias Ringwald // Example: If the output is 345 (Base 10), loop 2 times until Digit is 100. 1877dc86dfdSMatthias Ringwald // 1887dc86dfdSMatthias Ringwald while (1) { 1897dc86dfdSMatthias 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) 1907dc86dfdSMatthias Ringwald NumDigits--; 1917dc86dfdSMatthias Ringwald } else { 1927dc86dfdSMatthias Ringwald Div = v / Digit; 1937dc86dfdSMatthias Ringwald if (Div < Base) { // Is our divider big enough to extract the highest digit from value? => Done 1947dc86dfdSMatthias Ringwald break; 1957dc86dfdSMatthias Ringwald } 1967dc86dfdSMatthias Ringwald } 1977dc86dfdSMatthias Ringwald Digit *= Base; 1987dc86dfdSMatthias Ringwald } 1997dc86dfdSMatthias Ringwald // 2007dc86dfdSMatthias Ringwald // Output digits 2017dc86dfdSMatthias Ringwald // 2027dc86dfdSMatthias Ringwald do { 2037dc86dfdSMatthias Ringwald Div = v / Digit; 2047dc86dfdSMatthias Ringwald v -= Div * Digit; 2057dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, _aV2C[Div]); 2067dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 2077dc86dfdSMatthias Ringwald break; 2087dc86dfdSMatthias Ringwald } 2097dc86dfdSMatthias Ringwald Digit /= Base; 2107dc86dfdSMatthias Ringwald } while (Digit); 2117dc86dfdSMatthias Ringwald // 2127dc86dfdSMatthias Ringwald // Print trailing spaces if necessary 2137dc86dfdSMatthias Ringwald // 2147dc86dfdSMatthias Ringwald if ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == FORMAT_FLAG_LEFT_JUSTIFY) { 2157dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 2167dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 2177dc86dfdSMatthias Ringwald FieldWidth--; 2187dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, ' '); 2197dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 2207dc86dfdSMatthias Ringwald break; 2217dc86dfdSMatthias Ringwald } 2227dc86dfdSMatthias Ringwald } 2237dc86dfdSMatthias Ringwald } 2247dc86dfdSMatthias Ringwald } 2257dc86dfdSMatthias Ringwald } 2267dc86dfdSMatthias Ringwald } 2277dc86dfdSMatthias Ringwald 2287dc86dfdSMatthias Ringwald /********************************************************************* 2297dc86dfdSMatthias Ringwald * 2307dc86dfdSMatthias Ringwald * _PrintInt 2317dc86dfdSMatthias Ringwald */ 2327dc86dfdSMatthias Ringwald static void _PrintInt(SEGGER_RTT_PRINTF_DESC * pBufferDesc, int v, unsigned Base, unsigned NumDigits, unsigned FieldWidth, unsigned FormatFlags) { 2337dc86dfdSMatthias Ringwald unsigned Width; 2347dc86dfdSMatthias Ringwald int Number; 2357dc86dfdSMatthias Ringwald 2367dc86dfdSMatthias Ringwald Number = (v < 0) ? -v : v; 2377dc86dfdSMatthias Ringwald 2387dc86dfdSMatthias Ringwald // 2397dc86dfdSMatthias Ringwald // Get actual field width 2407dc86dfdSMatthias Ringwald // 2417dc86dfdSMatthias Ringwald Width = 1u; 2427dc86dfdSMatthias Ringwald while (Number >= (int)Base) { 2437dc86dfdSMatthias Ringwald Number = (Number / (int)Base); 2447dc86dfdSMatthias Ringwald Width++; 2457dc86dfdSMatthias Ringwald } 2467dc86dfdSMatthias Ringwald if (NumDigits > Width) { 2477dc86dfdSMatthias Ringwald Width = NumDigits; 2487dc86dfdSMatthias Ringwald } 2497dc86dfdSMatthias Ringwald if ((FieldWidth > 0u) && ((v < 0) || ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN))) { 2507dc86dfdSMatthias Ringwald FieldWidth--; 2517dc86dfdSMatthias Ringwald } 2527dc86dfdSMatthias Ringwald 2537dc86dfdSMatthias Ringwald // 2547dc86dfdSMatthias Ringwald // Print leading spaces if necessary 2557dc86dfdSMatthias Ringwald // 2567dc86dfdSMatthias Ringwald if ((((FormatFlags & FORMAT_FLAG_PAD_ZERO) == 0u) || (NumDigits != 0u)) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u)) { 2577dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 2587dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 2597dc86dfdSMatthias Ringwald FieldWidth--; 2607dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, ' '); 2617dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 2627dc86dfdSMatthias Ringwald break; 2637dc86dfdSMatthias Ringwald } 2647dc86dfdSMatthias Ringwald } 2657dc86dfdSMatthias Ringwald } 2667dc86dfdSMatthias Ringwald } 2677dc86dfdSMatthias Ringwald // 2687dc86dfdSMatthias Ringwald // Print sign if necessary 2697dc86dfdSMatthias Ringwald // 2707dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 2717dc86dfdSMatthias Ringwald if (v < 0) { 2727dc86dfdSMatthias Ringwald v = -v; 2737dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '-'); 2747dc86dfdSMatthias Ringwald } else if ((FormatFlags & FORMAT_FLAG_PRINT_SIGN) == FORMAT_FLAG_PRINT_SIGN) { 2757dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '+'); 2767dc86dfdSMatthias Ringwald } else { 2777dc86dfdSMatthias Ringwald 2787dc86dfdSMatthias Ringwald } 2797dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 2807dc86dfdSMatthias Ringwald // 2817dc86dfdSMatthias Ringwald // Print leading zeros if necessary 2827dc86dfdSMatthias Ringwald // 2837dc86dfdSMatthias Ringwald if (((FormatFlags & FORMAT_FLAG_PAD_ZERO) == FORMAT_FLAG_PAD_ZERO) && ((FormatFlags & FORMAT_FLAG_LEFT_JUSTIFY) == 0u) && (NumDigits == 0u)) { 2847dc86dfdSMatthias Ringwald if (FieldWidth != 0u) { 2857dc86dfdSMatthias Ringwald while ((FieldWidth != 0u) && (Width < FieldWidth)) { 2867dc86dfdSMatthias Ringwald FieldWidth--; 2877dc86dfdSMatthias Ringwald _StoreChar(pBufferDesc, '0'); 2887dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue < 0) { 2897dc86dfdSMatthias Ringwald break; 2907dc86dfdSMatthias Ringwald } 2917dc86dfdSMatthias Ringwald } 2927dc86dfdSMatthias Ringwald } 2937dc86dfdSMatthias Ringwald } 2947dc86dfdSMatthias Ringwald if (pBufferDesc->ReturnValue >= 0) { 2957dc86dfdSMatthias Ringwald // 2967dc86dfdSMatthias Ringwald // Print number without sign 2977dc86dfdSMatthias Ringwald // 2987dc86dfdSMatthias Ringwald _PrintUnsigned(pBufferDesc, (unsigned)v, Base, NumDigits, FieldWidth, FormatFlags); 2997dc86dfdSMatthias Ringwald } 3007dc86dfdSMatthias Ringwald } 3017dc86dfdSMatthias Ringwald } 3027dc86dfdSMatthias Ringwald } 3037dc86dfdSMatthias Ringwald 3047dc86dfdSMatthias Ringwald /********************************************************************* 3057dc86dfdSMatthias Ringwald * 3067dc86dfdSMatthias Ringwald * Public code 3077dc86dfdSMatthias Ringwald * 3087dc86dfdSMatthias Ringwald ********************************************************************** 3097dc86dfdSMatthias Ringwald */ 3107dc86dfdSMatthias Ringwald /********************************************************************* 3117dc86dfdSMatthias Ringwald * 3127dc86dfdSMatthias Ringwald * SEGGER_RTT_vprintf 3137dc86dfdSMatthias Ringwald * 3147dc86dfdSMatthias Ringwald * Function description 3157dc86dfdSMatthias Ringwald * Stores a formatted string in SEGGER RTT control block. 3167dc86dfdSMatthias Ringwald * This data is read by the host. 3177dc86dfdSMatthias Ringwald * 3187dc86dfdSMatthias Ringwald * Parameters 3197dc86dfdSMatthias Ringwald * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 3207dc86dfdSMatthias Ringwald * sFormat Pointer to format string 3217dc86dfdSMatthias Ringwald * pParamList Pointer to the list of arguments for the format string 3227dc86dfdSMatthias Ringwald * 3237dc86dfdSMatthias Ringwald * Return values 3247dc86dfdSMatthias Ringwald * >= 0: Number of bytes which have been stored in the "Up"-buffer. 3257dc86dfdSMatthias Ringwald * < 0: Error 3267dc86dfdSMatthias Ringwald */ 3277dc86dfdSMatthias Ringwald int SEGGER_RTT_vprintf(unsigned BufferIndex, const char * sFormat, va_list * pParamList) { 3287dc86dfdSMatthias Ringwald char c; 3297dc86dfdSMatthias Ringwald SEGGER_RTT_PRINTF_DESC BufferDesc; 3307dc86dfdSMatthias Ringwald int v; 3317dc86dfdSMatthias Ringwald unsigned NumDigits; 3327dc86dfdSMatthias Ringwald unsigned FormatFlags; 3337dc86dfdSMatthias Ringwald unsigned FieldWidth; 3347dc86dfdSMatthias Ringwald char acBuffer[SEGGER_RTT_PRINTF_BUFFER_SIZE]; 3357dc86dfdSMatthias Ringwald 3367dc86dfdSMatthias Ringwald BufferDesc.pBuffer = acBuffer; 3377dc86dfdSMatthias Ringwald BufferDesc.BufferSize = SEGGER_RTT_PRINTF_BUFFER_SIZE; 3387dc86dfdSMatthias Ringwald BufferDesc.Cnt = 0u; 3397dc86dfdSMatthias Ringwald BufferDesc.RTTBufferIndex = BufferIndex; 3407dc86dfdSMatthias Ringwald BufferDesc.ReturnValue = 0; 3417dc86dfdSMatthias Ringwald 3427dc86dfdSMatthias Ringwald do { 3437dc86dfdSMatthias Ringwald c = *sFormat; 3447dc86dfdSMatthias Ringwald sFormat++; 3457dc86dfdSMatthias Ringwald if (c == 0u) { 3467dc86dfdSMatthias Ringwald break; 3477dc86dfdSMatthias Ringwald } 3487dc86dfdSMatthias Ringwald if (c == '%') { 3497dc86dfdSMatthias Ringwald // 3507dc86dfdSMatthias Ringwald // Filter out flags 3517dc86dfdSMatthias Ringwald // 3527dc86dfdSMatthias Ringwald FormatFlags = 0u; 3537dc86dfdSMatthias Ringwald v = 1; 3547dc86dfdSMatthias Ringwald do { 3557dc86dfdSMatthias Ringwald c = *sFormat; 3567dc86dfdSMatthias Ringwald switch (c) { 3577dc86dfdSMatthias Ringwald case '-': FormatFlags |= FORMAT_FLAG_LEFT_JUSTIFY; sFormat++; break; 3587dc86dfdSMatthias Ringwald case '0': FormatFlags |= FORMAT_FLAG_PAD_ZERO; sFormat++; break; 3597dc86dfdSMatthias Ringwald case '+': FormatFlags |= FORMAT_FLAG_PRINT_SIGN; sFormat++; break; 3607dc86dfdSMatthias Ringwald case '#': FormatFlags |= FORMAT_FLAG_ALTERNATE; sFormat++; break; 3617dc86dfdSMatthias Ringwald default: v = 0; break; 3627dc86dfdSMatthias Ringwald } 3637dc86dfdSMatthias Ringwald } while (v); 3647dc86dfdSMatthias Ringwald // 3657dc86dfdSMatthias Ringwald // filter out field with 3667dc86dfdSMatthias Ringwald // 3677dc86dfdSMatthias Ringwald FieldWidth = 0u; 3687dc86dfdSMatthias Ringwald do { 3697dc86dfdSMatthias Ringwald c = *sFormat; 3707dc86dfdSMatthias Ringwald if ((c < '0') || (c > '9')) { 3717dc86dfdSMatthias Ringwald break; 3727dc86dfdSMatthias Ringwald } 3737dc86dfdSMatthias Ringwald sFormat++; 3747dc86dfdSMatthias Ringwald FieldWidth = (FieldWidth * 10u) + ((unsigned)c - '0'); 3757dc86dfdSMatthias Ringwald } while (1); 3767dc86dfdSMatthias Ringwald 3777dc86dfdSMatthias Ringwald // 3787dc86dfdSMatthias Ringwald // Filter out precision (number of digits to display) 3797dc86dfdSMatthias Ringwald // 3807dc86dfdSMatthias Ringwald NumDigits = 0u; 3817dc86dfdSMatthias Ringwald c = *sFormat; 3827dc86dfdSMatthias Ringwald if (c == '.') { 3837dc86dfdSMatthias Ringwald sFormat++; 3847dc86dfdSMatthias Ringwald do { 3857dc86dfdSMatthias Ringwald c = *sFormat; 3867dc86dfdSMatthias Ringwald if ((c < '0') || (c > '9')) { 3877dc86dfdSMatthias Ringwald break; 3887dc86dfdSMatthias Ringwald } 3897dc86dfdSMatthias Ringwald sFormat++; 3907dc86dfdSMatthias Ringwald NumDigits = NumDigits * 10u + ((unsigned)c - '0'); 3917dc86dfdSMatthias Ringwald } while (1); 3927dc86dfdSMatthias Ringwald } 3937dc86dfdSMatthias Ringwald // 3947dc86dfdSMatthias Ringwald // Filter out length modifier 3957dc86dfdSMatthias Ringwald // 3967dc86dfdSMatthias Ringwald c = *sFormat; 3977dc86dfdSMatthias Ringwald do { 3987dc86dfdSMatthias Ringwald if ((c == 'l') || (c == 'h')) { 3997dc86dfdSMatthias Ringwald sFormat++; 4007dc86dfdSMatthias Ringwald c = *sFormat; 4017dc86dfdSMatthias Ringwald } else { 4027dc86dfdSMatthias Ringwald break; 4037dc86dfdSMatthias Ringwald } 4047dc86dfdSMatthias Ringwald } while (1); 4057dc86dfdSMatthias Ringwald // 4067dc86dfdSMatthias Ringwald // Handle specifiers 4077dc86dfdSMatthias Ringwald // 4087dc86dfdSMatthias Ringwald switch (c) { 4097dc86dfdSMatthias Ringwald case 'c': { 4107dc86dfdSMatthias Ringwald char c0; 4117dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 4127dc86dfdSMatthias Ringwald c0 = (char)v; 4137dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c0); 4147dc86dfdSMatthias Ringwald break; 4157dc86dfdSMatthias Ringwald } 4167dc86dfdSMatthias Ringwald case 'd': 4177dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 4187dc86dfdSMatthias Ringwald _PrintInt(&BufferDesc, v, 10u, NumDigits, FieldWidth, FormatFlags); 4197dc86dfdSMatthias Ringwald break; 4207dc86dfdSMatthias Ringwald case 'u': 4217dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 4227dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 10u, NumDigits, FieldWidth, FormatFlags); 4237dc86dfdSMatthias Ringwald break; 4247dc86dfdSMatthias Ringwald case 'x': 4257dc86dfdSMatthias Ringwald case 'X': 4267dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 4277dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, NumDigits, FieldWidth, FormatFlags); 4287dc86dfdSMatthias Ringwald break; 4297dc86dfdSMatthias Ringwald case 's': 4307dc86dfdSMatthias Ringwald { 4317dc86dfdSMatthias Ringwald const char * s = va_arg(*pParamList, const char *); 4327dc86dfdSMatthias Ringwald do { 4337dc86dfdSMatthias Ringwald c = *s; 4347dc86dfdSMatthias Ringwald s++; 4357dc86dfdSMatthias Ringwald if (c == '\0') { 4367dc86dfdSMatthias Ringwald break; 4377dc86dfdSMatthias Ringwald } 4387dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c); 4397dc86dfdSMatthias Ringwald } while (BufferDesc.ReturnValue >= 0); 4407dc86dfdSMatthias Ringwald } 4417dc86dfdSMatthias Ringwald break; 4427dc86dfdSMatthias Ringwald case 'p': 4437dc86dfdSMatthias Ringwald v = va_arg(*pParamList, int); 4447dc86dfdSMatthias Ringwald _PrintUnsigned(&BufferDesc, (unsigned)v, 16u, 8u, 8u, 0u); 4457dc86dfdSMatthias Ringwald break; 4467dc86dfdSMatthias Ringwald case '%': 4477dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, '%'); 4487dc86dfdSMatthias Ringwald break; 4497dc86dfdSMatthias Ringwald default: 4507dc86dfdSMatthias Ringwald break; 4517dc86dfdSMatthias Ringwald } 4527dc86dfdSMatthias Ringwald sFormat++; 4537dc86dfdSMatthias Ringwald } else { 4547dc86dfdSMatthias Ringwald _StoreChar(&BufferDesc, c); 4557dc86dfdSMatthias Ringwald } 4567dc86dfdSMatthias Ringwald } while (BufferDesc.ReturnValue >= 0); 4577dc86dfdSMatthias Ringwald 4587dc86dfdSMatthias Ringwald if (BufferDesc.ReturnValue > 0) { 4597dc86dfdSMatthias Ringwald // 4607dc86dfdSMatthias Ringwald // Write remaining data, if any 4617dc86dfdSMatthias Ringwald // 4627dc86dfdSMatthias Ringwald if (BufferDesc.Cnt != 0u) { 4637dc86dfdSMatthias Ringwald SEGGER_RTT_Write(BufferIndex, acBuffer, BufferDesc.Cnt); 4647dc86dfdSMatthias Ringwald } 4657dc86dfdSMatthias Ringwald BufferDesc.ReturnValue += (int)BufferDesc.Cnt; 4667dc86dfdSMatthias Ringwald } 4677dc86dfdSMatthias Ringwald return BufferDesc.ReturnValue; 4687dc86dfdSMatthias Ringwald } 4697dc86dfdSMatthias Ringwald 4707dc86dfdSMatthias Ringwald /********************************************************************* 4717dc86dfdSMatthias Ringwald * 4727dc86dfdSMatthias Ringwald * SEGGER_RTT_printf 4737dc86dfdSMatthias Ringwald * 4747dc86dfdSMatthias Ringwald * Function description 4757dc86dfdSMatthias Ringwald * Stores a formatted string in SEGGER RTT control block. 4767dc86dfdSMatthias Ringwald * This data is read by the host. 4777dc86dfdSMatthias Ringwald * 4787dc86dfdSMatthias Ringwald * Parameters 4797dc86dfdSMatthias Ringwald * BufferIndex Index of "Up"-buffer to be used. (e.g. 0 for "Terminal") 4807dc86dfdSMatthias Ringwald * sFormat Pointer to format string, followed by the arguments for conversion 4817dc86dfdSMatthias Ringwald * 4827dc86dfdSMatthias Ringwald * Return values 4837dc86dfdSMatthias Ringwald * >= 0: Number of bytes which have been stored in the "Up"-buffer. 4847dc86dfdSMatthias Ringwald * < 0: Error 4857dc86dfdSMatthias Ringwald * 4867dc86dfdSMatthias Ringwald * Notes 4877dc86dfdSMatthias Ringwald * (1) Conversion specifications have following syntax: 4887dc86dfdSMatthias Ringwald * %[flags][FieldWidth][.Precision]ConversionSpecifier 4897dc86dfdSMatthias Ringwald * (2) Supported flags: 4907dc86dfdSMatthias Ringwald * -: Left justify within the field width 4917dc86dfdSMatthias Ringwald * +: Always print sign extension for signed conversions 4927dc86dfdSMatthias Ringwald * 0: Pad with 0 instead of spaces. Ignored when using '-'-flag or precision 4937dc86dfdSMatthias Ringwald * Supported conversion specifiers: 4947dc86dfdSMatthias Ringwald * c: Print the argument as one char 4957dc86dfdSMatthias Ringwald * d: Print the argument as a signed integer 4967dc86dfdSMatthias Ringwald * u: Print the argument as an unsigned integer 4977dc86dfdSMatthias Ringwald * x: Print the argument as an hexadecimal integer 4987dc86dfdSMatthias Ringwald * s: Print the string pointed to by the argument 4997dc86dfdSMatthias Ringwald * p: Print the argument as an 8-digit hexadecimal integer. (Argument shall be a pointer to void.) 5007dc86dfdSMatthias Ringwald */ 5017dc86dfdSMatthias Ringwald int SEGGER_RTT_printf(unsigned BufferIndex, const char * sFormat, ...) { 5027dc86dfdSMatthias Ringwald int r; 5037dc86dfdSMatthias Ringwald va_list ParamList; 5047dc86dfdSMatthias Ringwald 5057dc86dfdSMatthias Ringwald va_start(ParamList, sFormat); 5067dc86dfdSMatthias Ringwald r = SEGGER_RTT_vprintf(BufferIndex, sFormat, &ParamList); 5077dc86dfdSMatthias Ringwald va_end(ParamList); 5087dc86dfdSMatthias Ringwald return r; 5097dc86dfdSMatthias Ringwald } 5107dc86dfdSMatthias Ringwald /*************************** End of file ****************************/ 511