2013-02-17 16 views
5

私はSTM32F3 mc(STM32F3-Discovery)の埋め込みコードを書いています。私はいくつかのデータをUARTに出力する必要があります。これは、バイト転送の完了を待つのではなく、センサーの読み取りとデータ処理に集中することができるので、DMAを使用しています。問題は、しかし、私が結合していることである。循環バッファへの書式付き印刷

  1. 書式付き出力(前回のプリントが終了する前に発生)の連続プリント(すなわちprintf関数のからいくつかの)

だから私は、循環バッファーを考える。しかし、私は、バッファの終わりを尊重し、バッファの先頭に書き込みを続けるようにする方法を知っているとは思わない。私はもちろん、別の一時バッファを作成し、そこにプリントし、バイト単位でコピーすることはできますが、それは私にはエレガントではありません。

+1

興味深い要望ですが、「適切なコピー機能で循環バッファにコピーしてから、一時バッファにフォーマットする」よりもはるかに優れているとは思いません。 –

答えて

2

1つの解決策は、リングバッファで動作する独自のsprintfを実装することです。残念ながら、これはより基本的な問題に関してあなたを助けません:あなたのリングバッファがいっぱいで、あなたがsprintfを呼び出すなら、あなたはどうしますか?

あなたの記憶の状況は、私はこの問題の別の解決策をお勧めしたい、それを余裕がある場合は、次の

アイデアがバッファの2つのリンクされたリストに基づいています(空きバッファに1つのリスト、送信キューとして1個のリスト) 。バッファは、最悪の場合の長さの文字列を格納できるように、同じサイズです。バッファは単純なヒープを作成します。単純なヒープでは、割り振り/割り振り解除は、フリーまたは送信リストから要素をデキュー/エンキューするだけです。

同じサイズのバッファを使用すると、メモリを動的に割り当てるときに "checkerboarding"のような外部断片化の影響を受けないことが保証されます。この仕事のための独自のヒープを構築することは、送信タスクに利用可能な合計バッファサイズを完全に制御することにもなります。次のように

私は、このランニングを想像することができます:

  1. あなたがにデータをレンダリングするためにフリーリストからバッファを割り当てます。
  2. DMAについて

を送信キューに送信するデータを追加(および必要に応じて送信をトリガ)バッファ内のデータをレンダリングするために、あなたのレンダリング機能(suchasのはsprintf)を使用し、あなたを転送します転送終了IRQを処理します。そこでは、単に "フリーリスト"に転送されたバッファを移動し、キュー内の次のバッファへの転送を設定します。

このソリューションはメモリ効率が良いとは言えませんが、メモリに一度しか書き込むことはできません。割り当て/割り当て解除はどこかでポインタを取得/格納するためです。もちろん、割り当てと割り当て解除のためにアプリケーションとIRQとの間で競合条件が発生しないようにする必要があります。

多分このアイデアは、あなたの要件を解決するインスピレーションを与えます。

1

あなたが近似できる方法の1つは、printfバッファをリングバッファの2倍のサイズに割り当ててから、前半をリングバッファとして使用することです。オーバーフローを検出し、後半のオーバーフローをフロント(リング部分)にコピーします。

void xprintf(const char *format, ...) 
{ 
    int written; 
    va_list args; 
    va_start(args, format); 
    written = vsnprintf(buffer, HALF_BUFFER_SIZE, format, args); 
    va_end(args); 
    if (buffer + written > bufferStart + HALF_BUFFER_SIZE) 
    { // time to wrap 
    int overflow = (buffer + written) - (bufferStart + HALF_BUFFER_SIZE); 
    memmove(bufferStart, bufferStart + HALF_BUFFER_SIZE, overflow; 
    buffer = bufferStart + overflow; 
    } 
} 
関連する問題