2017-01-13 25 views
0

私は、STM32F0 DMAのUARTからのデータ受信に問題があります。私は2つのDMAチャンネル(rxとtxの両方)を非円形モードで使用し、rxチャンネルは低い優先順位を持っています。 UARTからのデータは、アイドルライン割り込みで処理されます。ここで、DMA受信バイト数を読み取り、処理します。パッケージ内のバイト数がDMAバッファサイズ以下になるまで、すべてうまく動作します。さもなければ、DMAが不意にオフになり、アイドルライン割り込みに続いて、1,0,0、...、DMA受信バイト数が私に与えられます。STM32F0 DMA「入力オーバーフロー」

#define S_M_INPUT_CMD_SIZE 20 
static char s_m_uart_dma_in_buff[S_M_INPUT_CMD_SIZE + 1]; 

void USART1_IRQHandler(void) 
{ 
    ITStatus reception_status = USART_GetITStatus(USART1, USART_IT_IDLE); 
    if(reception_status != RESET) 
    { 
     int32_t bytes_number = S_M_INPUT_CMD_SIZE - DMA_GetCurrDataCounter(DMA1_Channel3);    
     if (DMA_GetFlagStatus(DMA1_FLAG_TC3) != RESET) 
     { 
     USART_ITConfig(UART_, USART_IT_IDLE, DISABLE); 
     DMA_Cmd(DMA1_Channel3, DISABLE); 
     while (DMA1_Channel3->CCR & DMA_CCR_EN); 
     for (int i = 0; i < S_M_INPUT_CMD_SIZE; i++) 
      s_m_uart_dma_in_buff[i] = '\0'; 
     DMA_SetCurrDataCounter(DMA1_Channel3, S_M_INPUT_CMD_SIZE); 
     DMA_Cmd(DMA1_Channel3, ENABLE); 
     DMA_ClearFlag(DMA1_FLAG_GL3); 
     } 
     USART_ClearITPendingBit(UART_, USART_IT_IDLE); 
    } 
} 

最初の「オーバーフロー」とDMAを有効にするにはそのバイト「サイズ+ 1をバッファリング」に復帰した後:ここではDMAバッファがいっぱいとサイズをバッファリングするためにDMAカウンタをリセットしようとした場合、私はチェックコードの一部は、 rxレジスタにあり、後で受信バイト数が安定してゼロになりました。私は間違っているの?あなたのコード使用してS_M_INPUT_CMD_SIZEよりも大きなサイズのパケットを受信しようとするとどうなるかをここで

答えて

1

  1. ブロックS_M_INPUT_CMD_SIZEのDMA完全な受信をして(非円形モード)を無効
  2. USART1は1バイト
  3. を受け取ります
  4. USART1は、パケットから1つの以上のバイトを受信し、それらをドロップし、誰もがUART
  5. パケットが終了していないハンドルので、あなたがIDLE割り込みを取得し、DMA
  6. DMA REAをREINIT D以前に受信したバイト
  7. これ以上のパケット - あなたは、0を得る0、DMAの数はバイト

を受けた...私が言っている、これは実際にDMA転送を処理するための奇妙な方法です。 DMA転送は通常、周辺機器ではなくDMA割り込みハンドラで処理する必要があります。

長いパケットを処理するためには、DMA割り込みハンドラを実装する必要があります。したがって、IDLE割り込みよりも早くDMA受信を再開することができます。したがって、DMAはUARTからより多くのデータを受信する準備が整います。

もう1つ。あなたのコードにはレースがあります。あなたはbytes_numberを読んで、DMAを無効にすると、1つ以上のバイトがDMAによって転送される可能性があります。

しかし、UARTをより正確に処理するには、DMAを循環モードで実行し、再初期化しないでください。 DMAを無効にするたびに、UART入力をいくつか見逃す可能性があるためです。

+0

ご返信ありがとうございます@alexander。たぶん私はあなたを理解していないが、バイト番号 "0、0、..."を受け取った新しいアイドル中の割り込みで次のパッケージの反応は、ちょうど作業に疲れてDMAのようだ。 方法は奇妙ですが、これは私が最小のCPUコストで可変長パッケージを受け取るために思いついた唯一の方法です。 レースに感謝します。 – Yuriy

+0

@Yuriy、長いパケットの後に別のパケットを送りますか?そして、あなたはパケットをフォローするに '0'を得ますか? bytes_numberはどうやってチェックしますか? JTAGが実際の画像を壊す可能性があるので、ISRの内部でJTAGを使用してプログラムを停止することはできません。グローバル変数を使用してイベントを記録します。また、UARTとDMAが互いに同期していないこともあります(UARTやDMAをリセットする必要があります)。 UARTがオーバフローフラグをセットし、それをクリアするまで受信を停止することも可能です。 – alexander

+0

(bytes_number> 0)の場合、ゼロbytes_numberのチェックはスキップされます。 USARTとDMAを再接続しようとしましたが、DMA RCCを無効/有効にしようとしました。私は完全な再初期化を試みますが、それは良く見えません。 – Yuriy

関連する問題