是否可以在没有stdlibs的情况下写入控制台? C / C ++

我正在使用arm微处理器进行编程,并尝试通过UART使用print语句进行调试。 我不想仅为调试添加stdlibs 。 有没有办法在没有stdio.h / iostream.h情况下打印到控制台? 我可以自己编写printf()吗?

或者,我可以使用DMA控制器直接写入UART。 但是,我想避免这是可能的。 使用内置测试function“echo”或“remote loop-back”我知道我已正确配置UART。

简短回答:是的,完全有可能同时完成两种解决方案。

如果要支持所有数据类型和格式,printf函数非常复杂。 但是编写可以在几个不同的基础上输出字符串或整数的东西并不难(大多数人只需要十进制和hex,但是一旦你有十进制和hex,八进制可能只会添加另外3-4行代码)。

通常,printf的编写方式如下:

  int printf(const char *fmt, ...) { int ret; va_list args; va_start(args, fmt) ret = do_xprintf(outputfunc, NULL, fmt, args); va_end(args); return ret; } 

然后do_xprintf()为所有变体(printf,sprintf,fprintf等)完成所有艰苦的工作

 int do_xprintf(void (*outputfunc)(void *extra, char c), void *extra, const char *fmt, va_list args) { char *ptr = fmt; while(1) { char c = *ptr++; if (c == '%') { c = *ptr++; // Get next character from format string. switch(c) { case 's': char *str = va_arg(args, const char *); while(*str) { count++; outputfunc(extra, *str); str++; } break; case 'x': base = 16; goto output_number; case 'd': base = 10; output_number: int i = va_arg(args, int); // magical code to output 'i' in 'base'. break; default: count++; outputfunc(extra, c); break; } else count++; outputfunc(extra, c); } return count; } 

现在,您需要做的就是填写上面代码的几个部分并写一个输出到您的串行端口的outputfunc()。

请注意,这是粗略的草图,我确信代码中有一些错误 – 如果你想支持浮点或“宽度”,你将需要更多地工作…

(关于额外参数的注意事项 – 输出到FILE *指针的FILE * ,对于sprintf ,你可以传递缓冲区的结构和缓冲区中的位置,或类似的东西)

“控制台”的概念在您使用的特定系统的上下文之外没有太多意义。 通常在嵌入式程序中没有控制台的真正概念。

您正在寻找的是一种从您的系统中获取数据的方法。 如果您想使用UART,并且您没有使用像GNU / linux这样的高级操作系统,则需要编写自己的I / O驱动程序。 通常,这意味着首先通过寄存器写操作将UART配置为所需的分配/奇偶校验/流控制。 对于任何类型的强大IO,您都希望它是中断驱动的,因此您需要为使用循环缓冲区的tx和rx编写ISR。

完成后,您可以编写自己的printf,如Mats所示。

我找到了后台调试,将字符排入循环缓冲区,然后通过uart传输寄存器上的轮询程序排出,这是我选择的方法。

排队例程基于字符,字符串和可变大小(hex或固定宽度十进制)。 豪华缓冲程序可以指示溢出的保留字符。

该方法对目标操作的开销/影响最小,可以在中断例程中使用(小心),并且这个想法很容易转移,所以我忽略了我所使用的所有系统上的调试器。

由于通过嵌入式系统中的串口打印信息会修改主程序的时序,我发现的最佳解决方案是发送一个以2个字节编码的小消息(有时1个字节工作正常),然后使用PC解码这些消息并提供必要的信息,其中包括统计信息和您可能需要的所有信息。 这样,我只是在主程序中添加了一点开销,让PC完成了处理消息的艰苦工作。 也许是这样的:

  • 1字节消息:位7:4 =模块ID,位3:0 =调试信息。

  • 2字节消息:位15:12 =模块ID,位11:8 =调试信息,位7:0 =数据。

然后,在PC软件中,您必须声明一个表,其中包含映射到给定模块ID /调试信息对的消息,并使用它们在屏幕上打印。

也许它不像伪printf函数那么灵活,因为你需要在PC中解码一组固定的消息,但它并没有增加太多的开销,正如我之前提到的那样。

希望能帮助到你。

费尔南多