2

重複の可能性:
UART ISRTxRxアーキテクチャ

現在、DMAUARTドライバーと並列タスクをサポートするオペレーティングシステムを含むTIマイクロを使用しています。UARTドライバーの機能は次のとおりです。

  • static void HalUARTInitDMA(void);
  • static void HalUARTOpenDMA(halUARTCfg_t * config);
  • static uint16 HalUARTReadDMA(uint8 * buf、uint16 len);
  • static uint16 HalUARTWriteDMA(uint8 * buf、uint16 len);
  • static void HalUARTPollDMA(void);
  • static uint16 HalUARTRxAvailDMA(void);
  • static void HalUARTSuspendDMA(void);
  • static void HalUARTResumeDMA(void);

キャリッジリターンで終了したメッセージを受け入れ、その後キャリッジリターンでメッセージを応答する別の周辺機器と通信しようとしています。

このタイプの通信ステートマシンを設計するための最良の方法が何であるかを知りたいと思いました。私の問題は、UARTポートのコールバック関数を次のように設計することです...

  1. 応答を待ってシステムをハングさせません。(ある種のタイムアウト)
  2. 応答の読み取りが早すぎると、応答が連結されます
  3. キャリッジリターンはメッセージの終わりを意味します

基本的な理論は次のようなものです。

//send messsage to peripheral
HalUARTWriteDMA("tx\r",4);

//wait a little bit for the device to process the message

//start reading from the peripheral    
do {
    //how many bytes are at the RX port?
    int len = HalUARTRxAvailDMA();

    //Read those bytes
    HalUARTReadDMA(msg, len);

    //append the rx msg to the buffer
    strcat(rxbuf, msg)

    //does the response contain a CR?
} while(strchr(rxbuf, 0x0D));

このアイデアには明らかな欠陥がいくつかあります。この種のコミュニケーションがどのように行われるかについて、誰かがアイデアを共有してくれることを望んでいましたか?

ありがとう!

4

2 に答える 2

1

メッセージを待機しているスレッドをブロックする場合は、設計に直接的な問題が1つあります。これは、可変サイズのメッセージとCR区切り文字としての使用です。

これは、バイトが受信さHalUARTReadDMA()れるまで呼び出しスレッドをブロックするように設計されlenているため、可変長メッセージをブロックするために確実に使用することはできません。

コードは次のようになります(いくつかの仮定を行います):

while (1) 
{
    static const size_t bufferSize = sizeof(Message_t);
    uint8_t buffer[bufferSize];

    // blocks until message received 
    unsigned len = HalUARTReadDMA(buffer, bufferSize);

    if (len == bufferSize)
        processMessage(buffer);
}

DMAコントローラーがメッセージの終わりの区切り文字を検出できない限り、ポーリングを伴わないDMAで可変サイズのメッセージを使用する問題に対する特に優れたまたは信頼できる解決策はありません。
メッセージ形式を変更できない場合は、個々のメッセージバイトの受信をブロックする割り込み駆動型IOを使用することをお勧めします。特に、データレートが比較的低いUARTの場合はそうです。

于 2012-10-22T08:35:25.293 に答える
0

DMA ドライバーにバッファー ポインターのキューを受け入れる機能がなく、CR を受信したときに割り込みを生成し、独自に次のバッファー ポインターに移動できる場合を除き、rx データを反復処理して、 CR。

データを反復する必要がある場合は、「従来の」ISR で反復処理を行うこともできます。rx FIFO から文字を 1 つずつフェッチし、CR が受信されるまでそれらをバッファに押し込みます。

次に、バッファ ポインタを適切な循環キューにキューイングし、次のメッセージ用に「空の」バッファの別の循環プール キューから別のバッファをフェッチし、メッセージを処理するスレッドが実行されて終了するようにセマフォにシグナルを送ることができます。すぐに再スケジュールが実行されるように、OS を介して ISR から。

rx スレッドは、メッセージをデキューして処理し、ISR が再利用できるようにプール キューに再キューイングすることができます。

strchr() を使用して CR の完全なバッファを継続的に検索することは、特に効率的または簡単ではない可能性があります。CR が DMA バッファの途中にある可能性があり、リマイニング部分バッファのデータ コピーに関与する可能性があります。

.

于 2012-10-22T23:20:57.417 に答える