0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

AWorksLP应用笔记:重定向printf函数

ZLG致远电子 2023-11-25 08:24 次阅读

printf函数作为标准库定义的格式化输出方式,本文将介绍其在AWorksLP下默认适配以及重映射至热拔插设备端口的实现。

默认适配

AWorksLP中默认已经对printf函数完成相关适配工作,且默认被适配在UART设备。用户可以在图形化配置界面中使能 support the stdio functions ,并选择期望UART设备进行输出,具体配置如下图所示。

0745adc0-8b29-11ee-9788-92fbcf53809c.png

注:若用户未使能 stdio function 时,调用printf函数时,将不会有任何输出。

本文将使用 EPC6450-AWI 平台,选择标有丝印为DUART的调试串口(UART0设备)进行printf功能演示测试。将TTL转USB串口模块的TXD与板子的RXD丝印连接,RXD与板子的TXD丝印,将另一端的USB口接入电脑07591f5e-8b29-11ee-9788-92fbcf53809c.png启动串口调试助手,搜索并打开串口模块的设备端口号后,在工程中调用printf函数,根据下图可知,printf函数适配UART0设备成功。076d89e4-8b29-11ee-9788-92fbcf53809c.png

重定向至其他设备嵌入式的诸多应用在UART设备资源受限的情况下,可能存在将printf函数重定向到其他设备需求。为此,笔者将以EPC6450-AWI平台的USB串口设备为例进行说明。077d1c56-8b29-11ee-9788-92fbcf53809c.png1.实施步骤

与UART设备不同,USB设备为动态设备,因此重定向printf函数时,需要注意以下几个关键步骤:

1.1 支持NEWLIB标准库函数

由于AWorksLP中利用posix file相关操作接口对printf函数进行适配,故在重映射端口时,需将 support libc file operations 使能,并取消默认选择UART设备作为printf函数的适配,具体如下图所示。

08005670-8b29-11ee-9788-92fbcf53809c.png1.2 检测动态设备

USB设备为动态设备,因此需要持续检测设备的是否存在情况。可通过初始化一个动态设备检测任务,对设备的是否存在情况进行周期性检测。

while true: access (device) delay()

1.3 关联标准文件流

在检测到USB设备存在时,仅需将设备与标准文件流(stdio中的stdin、stdout、stderr,且在C库中被假定为交互设备,并约定了这些设备的文件描述符依次为0、1、2)关联起来。故在使用时,我们仅需将描述符0、1、2与USB串口设备即可,其伪代码如下所示。

while true: if access (device): 0 = open (device) duplicate 1 to 0 duplicate 2 to 0 delay()

1.4 清理文件描述符

检测到USB设备不存在时,需及时取消设备与标准文件流的关联。即根据设备的打开情况,对文件描述符进行清理,以便之后重新关联标准文件流。

while true: if access (device): 0 = open (device) duplicate 1 to 0 duplicate 2 to 0 else: close (device) delay()

2. 基础配置在EPC6450-AWI平台标有丝印为Type-C的接口处,插上Type-C线,将Type-C线的另一端USB口连接电脑。并在图形化配置界面,将USB设备选择为CDC串口设备。

0812e6e6-8b29-11ee-9788-92fbcf53809c.png

3.简单示例

static int __dynamic_stdin_fd = -1;static aw_err_t __dynamic_stdout_ret = -AW_EBADF;static aw_err_t __dynamic_stderr_ret = -AW_EBADF;
aw_err_t aw_printf_redirect_dynamic_dev(void){ int find = -AW_ENODEV;
// 检测动态设备 find = aw_access(AW_DYNAMIC_DEV_PATH, AW_F_OK);
if(find == AW_OK) { // 关联标准文件流 if(__dynamic_stdin_fd < 0)        {            __dynamic_stdin_fd = \             aw_open_at(AW_DYNAMIC_DEV_PATH,AW_O_RDWR,0,0);            __dynamic_stdout_ret = aw_dup2(0, 1);            __dynamic_stderr_ret = aw_dup2(0, 2);            return AW_OK;        }    }    else {        // 清理文件描述符        if(__dynamic_stdin_fd >= 0) { aw_close(0); __dynamic_stdin_fd = -1; } if (__dynamic_stdout_ret == AW_OK) { aw_close(1); __dynamic_stdout_ret = -AW_EBADF; } if (__dynamic_stderr_ret == AW_OK) { aw_close(2); __dynamic_stderr_ret = -AW_EBADF; } }
return -AW_ENODEV;}
int aw_main(void){ int ret;
aw_kprintf("hello world\n"); printf("hello world\n");
while(1) { ret = aw_printf_redirect_dynamic_dev(); if (AW_OK == ret) break;
// 设置检测周期 AW_TASK_DELAY(100); }
aw_kprintf("hello world, ZLG\n"); printf("hello world, ZLG\n");
return 0;}

启动串口调试助手,搜索并打开DEBUG UART设备与CDC串口设备的端口号后,运行上文示例程序。根据下图可知,USB设备枚举后,printf函数成功重定向到了CDC串口设备。0825bf28-8b29-11ee-9788-92fbcf53809c.png

0831239a-8b29-11ee-9788-92fbcf53809c.png


07799d06-8b29-11ee-9788-92fbcf53809c.jpg 总结实现重定向printf函数时主要关注以下两个关键点:

  1. 重写NEWLIB标准库中printf函数的底层实现;
  2. 将指定设备以标准文件流约定的文件描述符打开。


07799d06-8b29-11ee-9788-92fbcf53809c.jpg 扩展阅读

本文所演示平台使用的是GCC编译器,其对应C库为NEWLIB标准库。在AWorksLP中printf函数的底层输出接口在AWorksLP中实现为_write_r 函数,其具体代码实现如下所示。

__attribute__((__used__)) _ssize_t_write_r(struct _reent *ptr, int fd, const void *buf, size_t nbytes){ return aw_write(fd,buf,nbytes);}

需要值得注意的是,上述适配方式仅兼容NEWLIB,若是其他编译器,其实现以及接口不尽相同,下表仅给出部分以供参考,在使用时需根据实际情况进行调整。

工具链

标准库

底层接口

GCC

NEWLIB

_write_r

ARMCC

ARMCLIB

_sys_write

ARMCLANG

ARMCLIB

_sys_write

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 设备
    +关注

    关注

    2

    文章

    4172

    浏览量

    69279
  • uart
    +关注

    关注

    22

    文章

    1159

    浏览量

    99973
  • 函数
    +关注

    关注

    3

    文章

    3882

    浏览量

    61310
收藏 人收藏

    评论

    相关推荐

    STM8L051片子使用重定向printf函数时总是报错,没办法引用printf函数是什么原因?

    STM8L051片子使用重定向printf函数时总是报错,没办法引用printf函数,不知道是什么原因,使用的是IAR编译器,总是报内存不足
    发表于 04-28 08:05

    STM32CubeIDE中打印重定向报错怎么解决?

    HAL_UART_Transmit( huart1 , (uint8_t *) ch, 1, 0xFFFF);报错 printf重定向 报错../Core/Src/main.c:42:21: error: \'huart1\' undeclared 已添加stdio.h头
    发表于 04-03 07:33

    H7平台如何重定向sqrtf函数到RAM中运行?

    如题,H7平台如何重定向sqrtf函数到RAM中运行,这个函数是库函数,不能使用__ramfunc前缀,有什么方法或是例程,网上找了很多icf配置的方法,都不行,要不就是只放置到RAM
    发表于 03-27 06:40

    2分钟搞懂输出重定向

    视频最后我们通过重定向把标准输出写到了文件中,但是错误输出还是留在了屏幕上。
    的头像 发表于 01-15 16:41 301次阅读

    C语言printf函数族学习笔记

    printf 应该是学习C语言的第一个函数,我们都知道它是用于字符串格式化输出的。但是它的用法你真正了解了吗?
    的头像 发表于 11-24 11:15 546次阅读
    C语言<b class='flag-5'>printf</b><b class='flag-5'>函数</b>族学习<b class='flag-5'>笔记</b>

    MDK在串口打印出的时候怎么进行重定向

    MDK在串口打印出的时候怎么进行重定向
    发表于 10-11 07:45

    如何实现Printf()接口重定向到UART

    车规级MCU开发,不像PC端,包含stdio.h头文件就可以使用Printf()函数。为了实现PC端Printf()接口功能,需要在MCU端实现Printf()接口的"
    的头像 发表于 10-01 10:13 637次阅读
    如何实现<b class='flag-5'>Printf</b>()接口<b class='flag-5'>重定向</b>到UART

    在bash中如何进行各种文件重定向呢?

    本文会用以下测试程序,来演示在bash中,如何进行各种文件重定向
    的头像 发表于 08-25 09:31 698次阅读
    在bash中如何进行各种文件<b class='flag-5'>重定向</b>呢?

    GD32VF103的相关例程中如何完成printf重定向到串口的?

    GD32VF103的相关例程中,如何完成printf重定向到串口的?
    发表于 08-16 07:54

    Splashtop:利用USB设备重定向实现无缝远程办公

    USB设备重定向不仅仅是一个巧妙的技巧,它是一个强大的工具,为远程工作和娱乐开辟了广泛的可能性。在这里,我们将探讨一些真实的示例,说明如何在不同的任务和角色中充分发挥USB设备重定向的潜力。
    的头像 发表于 07-31 14:53 675次阅读

    STM32的printf函数重定向方法

    MicroLib提供了一个有限的stdio子系统,它仅支持未缓冲的stdin、stdout和stderr,那么也就是说勾选了Use MicroLib选项后,在代码工程中就可以使用printf()函数咯?
    的头像 发表于 07-10 16:22 1095次阅读
    STM32的<b class='flag-5'>printf</b><b class='flag-5'>函数</b><b class='flag-5'>重定向</b>方法

    使用printf()函数时默认UART0输出,请教如何重定向printf()到UART1?

    芯片:N76E003; 编译环境:keil5 使用printf()函数时默认UART0输出,请教如何重定向printf()到UART1?
    发表于 06-25 07:12

    esphttpd wifi连接和连接后重定向怎么处理?

    加载 esphttpd 固件后,一切正常,除了两个(最重要的事情): 连接到 ESP 接入点后的重定向。它重定向但从未加载,我必须多次按下 chrome 浏览器上的重新加载按钮,直到它加载索引页面
    发表于 05-19 06:53

    printf输出重定向的方法

    在 PC 上运行 C 语言时,prinf 输出的内容会打印在电脑显示器上,这是因为 prinf 默认的输出设备就是显示器。而当我们在单片机上,需要通过 printf 函数将信息打印到串口,就要对 printf
    的头像 发表于 05-14 16:22 3808次阅读
    <b class='flag-5'>printf</b>输出<b class='flag-5'>重定向</b>的方法

    Linux I/O重定向详解

    Linux I/O重定向可以定义为,更改从命令读取输入到命令发送输出的方式。你可以重定向命令的输入和输出。对于重定向符号,可以是 或者 | 。
    的头像 发表于 05-04 14:34 590次阅读