6

我已经实现fputcfgetc在 retarget.c 中通过 UART0 在 Cortex-M3 上成功使用 printf。

但是,我想要第二个 uart 通道来获取更多调试信息。如何使用 printf 像 UART0 一样完美地集成它?

例如,将 fprintf 用于自定义目标并检查fputc将字符发送到哪个目标。例如,用于正常输出fprintf(UART0,"..");和调试输出fprintf(UART1,"..");

但是我看不到是否为 stdout 调用了 fopen,所以我正在努力了解如何手动实现它。(如果我只是打电话fprintf(RANDOM_VALUE,..),我不知道这会如何表现。

我想一旦我将它定向到不同的“文件”,那么只需检查 fputc 中指向的内容,但这是我正在努力解决的 FILE 指针的初始设置。

也许有某种方法可以区分 stdout 和 stderr,尽管从两个单独的通道获取输入时我仍然遇到同样的问题。

微库中还有 fprintf 吗?如果没有,是否有更好的方法来实现这一点?

谢谢!

4

1 回答 1

10

fputc() 接受一个流指针参数,有两个标准输出流 stdin、stdout 和 stderr。在重定向的较低级别,它们分别与文件描述符 0、1 和 2 相关联,您可以使用此信息将 stderr 与设备驱动程序级别的备用 UART 相关联。

然后,您可以使用 stderr 输出调试数据:

fprintf (stderr, "Error reading file" ) ;

例如。

最小重定向(特定于 Keil ARM-MDK/RealView)可能如下所示:

struct __FILE 
{
    int handle;  
};

enum 
{
    STDIN_HANDLE,
    STDOUT_HANDLE,
    STDERR_HANDLE
} ;

FILE __stdin = {STDIN_HANDLE} ;
FILE __stdout = {STDOUT_HANDLE} ;
FILE __stderr = {STDERR_HANDLE} ;

int fputc(int ch, FILE *f) 
{
    int ret = EOF ;

    switch( f->handle )
    {
        case STDOUT_HANDLE :
            // Write character to UART0
            ...
            ret = ch ;
            break ;

        case STDERR_HANDLE :
            // Write character to UART1
            ...
            ret = ch ;
            break ;

        default :
            break ;

    return ret ;
}

显然,如果需要,这也是您可以挂接文件系统的地方,在这种情况下,您的 __FILE 结构无疑会有额外的成员。

如果您不想为此使用 stderr,则必须重新定位 fopen() 以将设备名称(例如“dbg:”)转换为所需端口的文件描述符,然后使用 stdio 输出到关联的流。

微库中还有 fprintf 吗?如果没有,是否有更好的方法来实现这一点?

文档会告诉你,但是是的。Microlib stdio 支持由#pragma import(__use_full_stdio)指令控制,文档不清楚如果不使用它会排除什么。尝试不使用它,如果缺少任何东西,请使用它。这就是说我会想象 printf() 是作为标准输出流的 fprintf() 实现的,所以如果你有 printf(),你就有 fprintf()。

于 2013-01-23T17:00:18.103 回答