STM32L433 Inactivo + DMA UART La recepción no recibe el número esperado de bytes

0

Actualmente tengo un problema con la recepción de paquetes largos a través de UART utilizando DMA en una MCU STM32L433. El UART está configurado para interrumpirse cuando la línea pasa a IDLE y luego proceso el byte recién recibido del búfer DMA circular utilizando el contador DMA actual frente a la posición anterior del contador.

Pero, solo estoy recibiendo 51 bytes de los 108 bytes esperados en el momento en que se dispara la interrupción IDLE.

El DMA está configurado para el modo circular que recibe continuamente 255 bytes. ¿Por qué el DMA no recibe todos los bytes enviados a través de UART con éxito? ¿Qué debo mirar?

El código de abajo es del controlador de interrupciones UART. Si coloco un punto de interrupción en la línea cyp_cmd_head, puedo ver que el DMA Counter está en 204, lo que equivale a 255-204 = 51 bytes que estoy recibiendo.

void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
#ifdef INTERRUPT_COUNTER
    UART1_IDLE_INT_COUNT++;
#endif

    //https://community.st.com/thread/41068-cubemx-feature-request-add-usart-rx-idle-handling Adrian Adamson Oct21 2017
    UBaseType_t uxSavedInterruptStatus;

    // Receive time-out interrupt
     if (__HAL_UART_GET_FLAG(&huart1, UART_FLAG_IDLE) == SET)
     {
         uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR(); // Enter Critical Section

         cyp_cmd_tail = cyp_cmd_head;
         cyp_cmd_head = huart1.RxXferSize -(uint16_t)huart1.hdmarx->Instance->CNDTR;
         //cyp_cmd_head = __HAL_DMA_GET_COUNTER(huart1.hdmarx);

        if (cyp_cmd_tail || cyp_cmd_head)
        { //Ignore case where the interrupt fires before any data is received, when both are zero
            uint8_t unprocessedBytes =0;
            if(cyp_cmd_tail > cyp_cmd_head)
            { //Wrapped around circular buffer
                unprocessedBytes = (cyp_cmd_head + CYP_BUFF_LENGTH) - cyp_cmd_tail;
            }
            else
            {
                unprocessedBytes = cyp_cmd_head - cyp_cmd_tail;
            }


            if (unprocessedBytes > 0)
            {
                    rxDMAStruct.len = unprocessedBytes;
                    for (uint8_t i=0; i<unprocessedBytes; i++)
                    {
                        if ((cyp_cmd_tail+i)<CYP_BUFF_LENGTH)
                        {
                            rxDMAStruct.buffer[i] = (uint8_t)cyp_cmd_buff[cyp_cmd_tail+i];
                            cyp_cmd_buff[cyp_cmd_tail+i] = 0x00;

                        }
                        else
                        {
                            rxDMAStruct.buffer[i] = (uint8_t)cyp_cmd_buff[cyp_cmd_tail-CYP_BUFF_LENGTH+i];
                            cyp_cmd_buff[cyp_cmd_tail-CYP_BUFF_LENGTH+i] = 0x00;
                        }
                    }
                    if ((unprocessedBytes <= 4) && (rxDMAStruct.buffer[0] == 0x4F) && (rxDMAStruct.buffer[1] == 0x4B)) //"OK"
                    {
                        sigfoxAT_OK_Received = TRUE;
                    }
                    else
                    {
                        xQueueSendToBackFromISR(DMARxQueue, (void *) &rxDMAStruct, 0xFFFF);
                    }

            }
         }
         __HAL_UART_CLEAR_IDLEFLAG(&huart1);
         taskEXIT_CRITICAL_FROM_ISR( uxSavedInterruptStatus ); // Done with the critical section
     }


  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  //memset(rxDMAStruct.buffer, 0x00 ,DMARxQueueArrSize);

     //https://community.st.com/message/165252-restore-circular-dma-rx-after-uart-error
    huart1.ErrorCode |= HAL_UART_ERROR_FE;    //-> framing error is not longer visible
    huart1.ErrorCode |= HAL_UART_ERROR_NE;   // -> noise error is not longer visible
    huart1.ErrorCode |= HAL_UART_ERROR_ORE; // -> overrun error is longer not visible


  /* USER CODE END USART1_IRQn 1 */
}
    
pregunta AJBotha

0 respuestas

Lea otras preguntas en las etiquetas