Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
printf_格式化输出
原创征文
调试
【嵌入式开发笔记】简要谈一谈嵌入式开发中重写printf的几种方法
发布于 2022-10-13 23:12:24 浏览:1662
订阅该版
[tocm] 【嵌入式开发笔记】简要谈一谈嵌入式开发中重写printf的几种方法 ## 抛砖引玉 我大概查阅并考证了一下,在嵌入式开发中重写printf大概有以下几种方法: #### 1 宏定义替换 比如将printf强制替换成rt_kprintf: ```c #define printf rt_kprintf ``` 有些已经实现了类似printf打印接口的平台,我们就可以简单地这么干! #### 2 直接重写printf函数的实现 这种就比较生硬,直接自定义一个printf函数,类似这样: ```c char buf[256]; int printf(const char *format,...) { va_list args; va_start(args, format); vsprintf(buf, format, args); va_end(args); usrt_send(buf, strlen(buf)); return 0; } ``` 先用vsprintf之类的函数把参数格式化成字符串数组,然后直接调用串口之类的驱动发送接口发出去。 有些小平台的芯片,不想引入太多的依赖,就会这么干! #### 3 重写fputc/putchar接口 这种做法就是在bsp层重写fputc/putchar接口,在接口里面调用串口驱动发送出去,类似这样: 可以参考:**bsp/stm32/stm32mp157a-st-discovery/board/CubeMX_Config/CM4/Src/openamp_log.c** ```c #if defined ( __CC_ARM) || (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #define PUTCHAR_PROTOTYPE int stdout_putchar(int ch) #elif __GNUC__ /* With GCC/RAISONANCE, small log_info (option LD Linker->Libraries->Small log_info set to 'Yes') calls __io_putchar() */ #define PUTCHAR_PROTOTYPE int __attribute__(( weak )) __io_putchar(int ch) #else #define PUTCHAR_PROTOTYPE int __attribute__(( weak )) fputc(int ch, FILE *f) #endif /* __GNUC__ */ #if defined (__LOG_UART_IO_) || defined (__LOG_TRACE_IO_) PUTCHAR_PROTOTYPE { /* Place your implementation of fputc here */ /* e.g. write a character to the USART1 and Loop until the end of transmission */ #if defined (__LOG_UART_IO_) extern UART_HandleTypeDef huart; HAL_UART_Transmit(&huart, (uint8_t *)&ch, 1, HAL_MAX_DELAY); #endif #if defined (__LOG_TRACE_IO_) log_buff(ch); #endif return ch; } ``` #### 4 仿照POSIX的实现,从文件描述符0/1/2上面做文章 这种实现方法,在rt-thread中也可以见到,例如: **bsp/qemu-vexpress-a9** 我们可以通过反编译跟踪一下printf的调用轨迹: ```c 341970 60086be4
: 341971 printf(): 341972 60086be4: b40f push {r0, r1, r2, r3} 341973 60086be6: f24a 4288 movw r2, #42120 ; 0xa488 341974 60086bea: b500 push {lr} 341975 60086bec: f2c6 0209 movt r2, #24585 ; 0x6009 341976 60086bf0: b083 sub sp, #12 341977 60086bf2: ab04 add r3, sp, #16 341978 60086bf4: 6810 ldr r0, [r2, #0] 341979 60086bf6: f853 2b04 ldr.w r2, [r3], #4 341980 60086bfa: 6881 ldr r1, [r0, #8] 341981 60086bfc: 9301 str r3, [sp, #4] 341982 60086bfe: f002 fbdd bl 600893bc <_vfprintf_r> 341983 60086c02: b003 add sp, #12 341984 60086c04: f85d eb04 ldr.w lr, [sp], #4 341985 60086c08: b004 add sp, #16 341986 60086c0a: 4770 bx lr ``` 最终调用的是 **_vfprintf_r** 同时,我们在 **build_v2/kernel/components/libc/posix/io/stdio/libc.c** 中可以看到: ```c int libc_system_init(void) { #ifdef RT_USING_POSIX_STDIO rt_device_t dev_console; dev_console = rt_console_get_device(); if (dev_console) { libc_stdio_set_console(dev_console->parent.name, O_RDWR); } #endif /* RT_USING_POSIX_STDIO */ return 0; } INIT_COMPONENT_EXPORT(libc_system_init); ``` 通过这个libc_stdio_set_console接口,就通过将console设备驱动(比如串口)跟文件句柄输入、输出、错误绑在一块,这就回到了标准C库的实现逻辑了。 值得注意的是,这里调用printf还会调用编译器里面的c库: ```c compiler/gcc-arm-none-eabi-9-2019-q4-major/Linux64/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/lib/thumb/v7/nofp/libc.a(lib_a-printf.o) rtthread.map:7287:printf ``` ## 总结 以上就是我总结的几种实现方法,也有可能不一定全对,欢迎大家指正。 如果你有更好的思路或实现方法,也欢迎拿出来讨论。
2
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
李肯陪你玩赚嵌入式
2022年度和2023年度RT-Thread社区优秀开源布道师,COC深圳城市开发者社区主理人,专注于嵌入式物联网的架构设计
文章
47
回答
504
被采纳
82
关注TA
发私信
相关文章
1
程序下载之后无法正常运行
2
studio调试的时候直接跳到系统OTP出不来!下载运行正常!
3
STLINK调试无法进入
4
裸机添加nano后,为什么调试模式,多次点击全速才可以运行?
5
想使用keil5软件进行调试有什么好的视频或者网站能学习吗
6
单步调试出现问题参数显示错误
7
QEMU调试界面返回
8
Env仿真器硬件调试
9
st-link调试成功但找不到main
10
RT stduio无法进入调试
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
PWM
cubemx
flash
freemodbus
BSP
packages_软件包
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
编译报错
Debug
rt_mq_消息队列_msg_queue
SFUD
keil_MDK
msh
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1444
个答案
290
次被采纳
张世争
812
个答案
177
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
2
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
2
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
2
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部