博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Formatted print to circular buffer -- xprintf
阅读量:6358 次
发布时间:2019-06-23

本文共 3229 字,大约阅读时间需要 10 分钟。

 

I'm writing embedded code for STM32F3 mc (STM32F3-Discovery). I need to output some data to UART and I'm using DMA for this as this allows me to concentrate on sensors reading and data processing rather than on waiting for byte transmission completion. The issue however is that I have to combine:

  1. Formatted output (i.e. some from of printf)
  2. A number of consecutive prints (that occur before previous print has finished)

So I'm thinking about a circular buffer. But I don't think I know how to make sprintf to respect the end of buffer and continue writing to the beginning of the buffer. I can of course create another temporary buffer, print there, and copy byte-by-byte, but it doesn't look elegant to me.

One solution could be to implement your own sprintf which is able to work with ring buffers. Unfortunately this won't help you out regarding a more basic problem: What would you do if your ringbuffer is full and you invokesprintf?

If your memory situation can afford it, I'd suggest another solution for this problem:

The idea is based on two linked lists of buffers (one list for the free buffers, one list as transmit queue). The buffers are equally sized so they can store a worst case length string. The buffers build a simple heap where allocation/deallocation is only dequeuing/enqueuing an element either from the free or from the transmission list.

Having equally sized buffers guarantees you don't suffer from outer fragmentation effects like "checkerboarding" while allocating memory dynamically. Building your own heap for this job would also give you full control over the total buffer size available for transmission tasks.

I could imagine this running as follows:

  1. You allocate a buffer from the free list to render the data into.
  2. Use your render functions (suchas sprintf) to render the data in the buffer
  3. Append the data to be sent to the transmission queue (and trigger a transmission if necessary)

For the DMA transfer you handle the transfer end IRQ. There you move the buffer just transferred to the "free list" and setup the transfer for next buffer in the queue.

This solution won't be the memory efficientiest but the runtime efficiency is good as you only write to the memory once and the allocation/deallocation is only fetching/storing a pointer somewhere. Of course you'll have to make sure that you don't get race conditions between your application and the IRQ for allocation/deallocation.

Maybe this idea gives you an inspiration to solve your requirements.

One way you could approximate it is to allocate your printf buffer as 2x the size of your ringbuffer, and then use the first half as your ring buffer. Detect an overflow, copy the overflow in the latter half back to the front (the ring portion). Something like this:

 

1 void xprintf(const char *format, ...) 2 { 3   int written; 4   va_list args; 5   va_start(args, format); 6   written = vsnprintf(buffer, HALF_BUFFER_SIZE, format, args); 7   va_end(args);  8   if (buffer + written > bufferStart + HALF_BUFFER_SIZE) 9   { // time to wrap10     int overflow = (buffer + written) - (bufferStart + HALF_BUFFER_SIZE); 11     memmove(bufferStart, bufferStart + HALF_BUFFER_SIZE, overflow;12     buffer = bufferStart + overflow;13   }14 }

 

转载地址:http://jifma.baihongyu.com/

你可能感兴趣的文章
网站设计之合理架构CSS 架构CSS
查看>>
OTP 22.0 RC3 发布,Erlang 编写的应用服务器
查看>>
D语言/DLang 2.085.1 发布,修复性迭代
查看>>
感觉JVM的默认异常处理不够好,既然不好那我们就自己来处理异常呗!那么如何自己处理异常呢?...
查看>>
Java 基础 之 算数运算符
查看>>
Windows下配置安装Git(二)
查看>>
一个最简单的基于Android SearchView的搜索框
查看>>
铁路开通WiFi“钱景”不明
查看>>
Facebook申请专利 或让好友及陌生人相互拼车
查看>>
电力“十三五”规划:地面光伏与分布式的分水岭
查看>>
美联社再告FBI:要求公开请黑客解锁iPhone花费
查看>>
三星电子出售希捷和夏普等四家公司股份
查看>>
任志远:当云计算遇上混合云
查看>>
思科联手发那科 用物联网技术打造无人工厂
查看>>
智慧城市首要在政府利用大数据的智慧
查看>>
2015年物联网行业:巨头展开专利大战
查看>>
以自动化测试撬动遗留系统
查看>>
网络安全初创公司存活之道
查看>>
《图解CSS3:核心技术与案例实战》——1.2节浏览器对CSS3的支持状况
查看>>
《Android应用开发》——2.4节应用类
查看>>