我需要在嵌入式系统中将可变数量的字符打印为十六进制以进行调试
I need to print a variable number of chars as hex in an embedded system for debugging
在 C 中,我需要在嵌入式系统中将可变数量的字符打印为十六进制以进行调试。因为这是调试跟踪宏的一部分,所以我想避免 printf
无法处理的循环或其他逻辑。我也不想声明任何新变量来防止 Heisenbug 问题。输出 space 也是一个问题,因此我想将其转储为十六进制。
uint8_t* buffer;
uint8_t length;
MakeString(*message, &buffer, &length); //Function that puts some values in buffer and sets length
我正在寻找一个可以使用缓冲区和长度来生成如下内容的 printf:
0x1A1B1C0A02
对于 {1A,1B,1C,0A,02} 的值和长度 = 5
我知道 %.*s
或 %*
可以处理大小变量。没有 for/while 循环,有什么办法可以做到这一点吗?
没有。
我想你可以挂起一些串行端口缓冲区情感中断,它从缓冲区读取一个字节并在串行端口上发出两个字节...本身没有循环 .
或者做一些像这样卑鄙的事情(这个例子只对长度 0 到 10 有效)
int printbuf(unsigned char*buffer,int length)
{
#define b(x) buffer[x<length?x:0]
return printf("%02h%02h%02h%02h%02h%02h%02h%02h%02h%02h%02h"+4*(10-length)
,b(0),b(1),b(2),b(3),b(4),b(5),b(6),b(7),b(8),b(9));
#undef b
}
但是 sprintf 本身包含循环...
我过去使用过如下内容:
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 = '[=10=]';
}
它使用的唯一内存是静态和常量,所以它通常分配在 BSS 中。如果你有一个内存映射输出设备,那么你可以简化它并省略输出缓冲区并直接写入内存位置。您可以对其进行更多优化并将其隐藏在宏后面,以便您可以在发布版本中省略它。
我工作的系统没有 printf
或 sprintf
实现,因此我们通常会推出自己的十六进制转储代码。
在 C 中,我需要在嵌入式系统中将可变数量的字符打印为十六进制以进行调试。因为这是调试跟踪宏的一部分,所以我想避免 printf
无法处理的循环或其他逻辑。我也不想声明任何新变量来防止 Heisenbug 问题。输出 space 也是一个问题,因此我想将其转储为十六进制。
uint8_t* buffer;
uint8_t length;
MakeString(*message, &buffer, &length); //Function that puts some values in buffer and sets length
我正在寻找一个可以使用缓冲区和长度来生成如下内容的 printf:
0x1A1B1C0A02
对于 {1A,1B,1C,0A,02} 的值和长度 = 5
我知道 %.*s
或 %*
可以处理大小变量。没有 for/while 循环,有什么办法可以做到这一点吗?
没有。
我想你可以挂起一些串行端口缓冲区情感中断,它从缓冲区读取一个字节并在串行端口上发出两个字节...本身没有循环 .
或者做一些像这样卑鄙的事情(这个例子只对长度 0 到 10 有效)
int printbuf(unsigned char*buffer,int length)
{
#define b(x) buffer[x<length?x:0]
return printf("%02h%02h%02h%02h%02h%02h%02h%02h%02h%02h%02h"+4*(10-length)
,b(0),b(1),b(2),b(3),b(4),b(5),b(6),b(7),b(8),b(9));
#undef b
}
但是 sprintf 本身包含循环...
我过去使用过如下内容:
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 = '[=10=]';
}
它使用的唯一内存是静态和常量,所以它通常分配在 BSS 中。如果你有一个内存映射输出设备,那么你可以简化它并省略输出缓冲区并直接写入内存位置。您可以对其进行更多优化并将其隐藏在宏后面,以便您可以在发布版本中省略它。
我工作的系统没有 printf
或 sprintf
实现,因此我们通常会推出自己的十六进制转储代码。