良许Linux教程网 干货合集 网上最好的printf? 移植和例程!

网上最好的printf? 移植和例程!

近期在忙于应付其他事务,导致我内心自由飞翔的渴望受到了严重影响。因此,我今天想要向大家推荐一个由麻省理工的年轻工程师编写的printf家族的函数。据说,这个函数在网上被誉为目前嵌入式系统中最出色的printf函数。

在嵌入式系统中,printf函数可以说是C语言库函数中的一股清流,其功能强大,实在是太好用了!而今我将分享两款芯片的移植例程和移植教程,分别为stm32f4ZG和cc2530f256。我相信,看完后你也可以将这些例程成功移植到其他芯片上去!

需要注意的是,所使用的keil版本为5.21a,而IAR for 8051版本为10.10.1。不同版本可能会有略微不同的配置。这和我之前博客中介绍的printf方式的原理可能会有所区别。接下来,让我们先来看看实际的结果。

(f4)串口1:

image-20240306213501031
image-20240306213501031

(f4)串口2:

image-20240306213512521
image-20240306213512521

下面这个是TI 的cc2530(就先跑着寄存器版本的吧,协议栈里头配置差不太多!):

image-20240306213517044
image-20240306213517044

为啥要移植呢!相信学过实时操作系统的都有所了解有个叫信号互斥量的东西!就是为了防止同一时间内有两个寄存器(那十来个寄存器,不是指外设!)在访问同一块内存!

这个很严重的,可能会导致程序死机,或者卡在了某个死循环里面!

我们所使用的printf就是过首先vsprinf 通过对我们传进来的参数进行格式化,我们传进去多少数据他按照我们传进来的格式,格式化就统统存放在一个buf里,如果我们定义了重定向,它就会把这个buf发送至你要发送的地方!

想象一下如果在某个系统中有一个线程在vsprintf里面运行,突然有一个任务级别比他高的任务把它运行的时间抢了过去!而任务优先级高的任务也在printf里面使用了那个buf,那就会产生上述的问题!

那就意味着我们所使用的printf不安全问题!当然我们在系统中可以通过临界保护区来处理,也可以通过信号量等等处理!

但是目前有一个线程安全的函数,摆在你面前,就问你用不用?

咳咳,那我们的上边printf_u1它是怎么处理的呢?毫无疑问的看代码就能知道,它是直接发送的,也就是说你传进来的每一个参数它都会顺手就发送出去(当然要看你配置),它的数据将不会存放在一个buf里边,在发送。这就是他给力的地方了!

keil移植printf

首先我们到文章的末尾获取到源代码后,打开keil软件, 点击 project > Options for…就能打开一下页面:

image-20240306213521640
image-20240306213521640

点击 C/C++,选择c99标准。到此为止编译器配置完毕!

下面来配置代码部分,打开头文件为printf.h:

image-20240306213527608
image-20240306213527608

代码可在文末获取。

1,添加这个两个文件的路径还有头文件,如果不懂可以搜搜!

2,点击图片上面的printf_ 去它定义的地方,我们要做出一定的修改。

image-20240306213531510
image-20240306213531510

来到这里之后我们可以看到_vsprintf 这个代码里面最复杂的就是这一串函数了!

//我们只需要关心第一个参数即可!它是一个函数指针
static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const char* format, va_list va)
//指向了一个参数为下图的函数,返回值为void
typedef void (*out_fct_type)(char character, void* buffer, size_t idx, size_t maxlen);

putchar 里面的内容即可。参数二是我加上去的为了区分不同的串口类型,有多少个串口就的写多少个_out_char 这样的函数(这个是我的方法):

static inline void _out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
  (void)buffer; (void)idx; (void)maxlen;
  if (character) 
  {
    _putchar(character,1);
  }
}

上图是串口1的。

再来看看串口2的:

int printf_u2(const char* format, ...)
{
  va_list va;
  va_start(va, format);
  char buffer[1];
  const int ret = _vsnprintf(u2_out_char, buffer, (size_t)-1, format, va);
  va_end(va);
  return ret;
}
//注意vsprintf第一参数
static inline void u2_out_char(char character, void* buffer, size_t idx, size_t maxlen)
{
  (void)buffer; (void)idx; (void)maxlen;
  if (character) {
    _putchar(character,2);
  }
}

而_putchar 就是我们数据最终流向的地方了!我是这样写的。

void _putchar(char character,char sw)
{
  // send char to console etc.
  if(sw == 1)
  {
    while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
    USART1->DR = (u8) character;
  }
  if(sw == 2)
  {
  while((USART2->SR&0X40)==0);//循环发送,直到发送完毕
     USART2->DR = (u8) character;
  }
  if(sw == 3)
  {
  while((USART3->SR&0X40)==0);//循环发送,直到发送完毕
     USART3->DR = (u8) character;
  }
}

USART3->DR 这个为stm32串口的寄存器!读者可参照自己的芯片来配置!

简单就完了!

IAR 配置方法

首先添加文件:

image-20240306213535674
image-20240306213535674

我在这里起名字为 C_Library。然后在添加文件:

image-20240306213539483
image-20240306213539483

选择printf.c(反正最是添加这个文件,放到哪里看你自己):

image-20240306213542705
image-20240306213542705

接着就是添加编译器头文件路径:

image-20240306213546263
image-20240306213546263
image-20240306213549471
image-20240306213549471

在选择第一个大框框右边的那个:

image-20240306213552833
image-20240306213552833

点击Click to add。选择头文件路径所在的文件夹后 select,接着就会回到这里:

image-20240306213556114
image-20240306213556114

上面是配置头文件路径的,第一个是绝对路径,也就是说你工程文件移动了,就回到不到了,第二个是相对路径!选第二个吧!

接着编译就会发现报错了!!!

不要慌!我们首先选择Options > General Options:

image-20240306213559015
image-20240306213559015

此时在编译一次,就会发现也还是错了!说什么没定义。

经研究,哦,原来是stdint.h这个头文件在for 8051 这款工具上,没有定义64为的无符号整形,那个怎么办啊!

经发现,哦 ,原来注释这个宏就行!

image-20240306213602331
image-20240306213602331

程序编译通过!printf_u0 和stm32 配置类型,无非就是修改一下数据的流向!读者自己研究一下吧!!

image-20240306213608223
image-20240306213608223

以上就是良许教程网为各位朋友分享的Linu系统相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多干货等着你 !

137e00002230ad9f26e78-265x300
本文由 良许Linux教程网 发布,可自由转载、引用,但需署名作者且注明文章出处。如转载至微信公众号,请在文末添加作者公众号二维码。
良许

作者: 良许

良许,世界500强企业Linux开发工程师,公众号【良许Linux】的作者,全网拥有超30W粉丝。个人标签:创业者,CSDN学院讲师,副业达人,流量玩家,摄影爱好者。
上一篇
下一篇

发表评论

联系我们

联系我们

公众号:良许Linux

在线咨询: QQ交谈

邮箱: yychuyu@163.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部