2017-01-13 4 views
0

STM32F0 DMA가 UART로부터 데이터를 수신하는 데 문제가 있습니다. 두 개의 DMA 채널 (rx 및 tx 용)을 둘 다 비 원형 모드로 사용하면 rx 채널의 우선 순위가 낮아집니다. Idle Line 인터럽트의 UART 데이터는 DMA 수신 바이트 수를 읽고 처리합니다. 패키지의 바이트 수가 DMA 버퍼 크기보다 작거나 같을 때까지 모든 것이 잘 작동합니다. 그렇지 않으면 DMA가 이상하게 꺼지고 Idle Line 인터럽트를 따라 가면 1, 0, 0, ... DMA 수신 바이트 수를 알 수 있습니다. 여기서 I는 DMA 버퍼가 차면 확인 크기 버퍼 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 버퍼"그 rx 레지스터에 있었고 나중에 수신 된 바이트 수는 안정적인 0입니다. 내가 뭘 잘못하고있어? 당신이 S_M_INPUT_CMD_SIZE이 코드를 사용하는 것보다 더 큰 크기의 패킷을 수신하려고하면

답변

1

여기에 무슨 일이 :

는 블록 S_M_INPUT_CMD_SIZE의
  1. DMA 완벽한 수신 및 비활성화 (비 원형 모드)
  2. USART1 한 바이트를받을
  3. 아무도
  4. DMA 것이란 DMA를
  5. 패킷을 완료, 당신은 IDLE 인터럽트를 얻을 UART를 처리하지 않고 REINIT 때문에
  6. USART1는 패킷에서 하나 이상의 바이트를 수신하고 드롭 D 이전에 바이트를
  7. 더 이상 패킷을받은 - 당신은 0, 0, ... DMA의 수 바이트
  8. 내가 말을해야

을받은 얻을,이 DMA 전송을 처리 할 수있는 정말 이상한 방법입니다. 일반적으로 DMA 전송은 주변 장치가 아닌 DMA 인터럽트 처리기에서 처리해야합니다.

긴 패킷을 처리하려면 DMA 인터럽트 처리기를 구현해야합니다. 따라서 IDLE 인터럽트보다 빨리 DMA 수신을 다시 시작할 수 있습니다. 따라서 DMA는 UART로부터 더 많은 데이터를 수신 할 준비가됩니다.

한 가지 더. 당신의 코드에는 경주가 있습니다. 당신은 bytes_number을 읽고 DMA를 비활성화하면 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

0 bytes_number 검사가 (bytes_number> 0)이면 건너 뜁니다. USART와 DMA를 다시 연결하려고 시도했으며 DMA RCC를 사용 불가능하게 설정하려고했습니다. 전체 재 초기화를 시도하지만 좋지 않습니다. – Yuriy