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