Search code examples
cprintfhexdump

I need to print a variable number of chars as hex in an embedded system for debugging


In C I need to print a variable number of chars as hex in an embedded system for debugging. As this is part of a debug trace macro I want to avoid loops or other logic that printf can't handle. I also don't want to declare any new variables to prevent Heisenbug issues. Output space is also an issue so I want to dump it in hex.

uint8_t* buffer;
uint8_t length;

MakeString(*message, &buffer, &length);  //Function that puts some values in buffer and sets length

I'm looking for a printf that can take buffer and length to produce something like:

0x1A1B1C0A02

for values of {1A,1B,1C,0A,02} and length = 5

I know that %.*s or %* can handle size variables. Is there any way to do this without a for/while loop?


Solution

  • I've use stuff like the following in the past:

    void
    to_hex(char *output, size_t out_len, uint8_t const *input, size_t in_len)
    {
            static const char digits[] = "0123456789abcdef";
            if (out_len < 1) {
                    return;
            }
    
            --out_len; /* reserve space for that NUL terminator */
            while (out_len > 1 && in_len) {
                    *output++ = digits[(*input & 0xF0) >> 4];
                    *output++ = digits[*input & 0x0F];
                    out_len -= 2;
                    ++input, --in_len;
            }
            if (in_len) {
                    *output++ = digits[(*input & 0xF0) >> 4];
            }
            *output = '\0';
    }
    

    The only memory that it is uses is static and const so it is usually allocated in the BSS. If you have a memory-mapped output device, then you can simplify this and omit the output buffer and write directly to the memory location. You could optimize this a lot more and hide it behind a macro so you can omit it in release builds.

    The systems that I worked on didn't have a printf or sprintf implementation, so we usually rolled our own hex dump code.