STM32: использовать USART с символьным соответствием ISR и буфером DMA - PullRequest
4 голосов
/ 31 октября 2019

Я использую устройство STM32L432 с FreeRTOS и STM32CubeMX.

Я пытаюсь реализовать M2M-связь через USART на основе протокола ASCII. Последовательности протокола могут отличаться по длине, но иметь максимальную длину и определенный конечный символ (' \ r ' / 0x0D ).

Поэтому я подумал о сборе всехДанные RX-USART с DMA (например, FIFO ) и использованием isr совпадения адресов на основе флага USART_ICR_CMCF для определения конечного символа.

Инициализация USART1 и включение адресаmatch isr

void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle) {
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(uartHandle->Instance==USART1) {
    /* USART1 clock enable */
    __HAL_RCC_USART1_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* USART1 interrupt Init */
    HAL_NVIC_SetPriority(USART1_IRQn, 5, 0);
    HAL_NVIC_EnableIRQ(USART1_IRQn);

    /* USER CODE BEGIN USART1_MspInit 1 */
    USART1->CR2 |= 0x0D000000; // \r 0x0D
    __HAL_UART_ENABLE_IT(&huart1,UART_IT_CM);
  }
}

USART1 обработчик isr

void USART1_IRQHandler(void) {
  if (USART1->ISR & USART_ISR_CMF) {
    data = USART1->RDR;  
    SET_BIT(USART1->ICR,USART_ICR_CMCF);
  }
  HAL_UART_IRQHandler(&huart1);
}

В данный момент адрес соответствия isr работает нормально, но у меня нет идеикак реализовать поддержку DMA / FIFO.

Кстати:

Я был очень удивлен, что устройство не поддерживает USART HW FIFO. Моя идея использовать DMA для воспроизведения FIFO обычно используется?

1 Ответ

4 голосов
/ 05 ноября 2019

Смысл DMA состоит в том, чтобы не задействовать процессор в каждом передаваемом байте. Если ваш ISR вызывается для каждого байта, тогда задействуется процессор, поэтому одновременное включение DMA, если это вообще возможно, не даст никаких преимуществ в производительности. Избавьтесь от любого из двухбайтовых прерываний или прямого доступа к памяти. Если вы определенно хотите проверить наличие определенного символа по мере его поступления, то DMA не поможет.

Другой популярный подход для определения конца ввода при использовании ввода произвольной длины вместе с DMA - это использование прерывания бездействия USART. Это прерывание срабатывает, когда время одного байта (время, необходимое для передачи одного байта с текущей скоростью передачи) истекает без какой-либо передачи. В этом прерывании вы можете перенести содержимое буфера DMA в другое место в памяти, затем повторно инициализировать DMA для последующего ввода и оставить. Или вы можете обработать ввод тогда и там. Вы можете делать все, что хотите, в режиме ожидания ISR, если ISR быстро завершает выполнение.

Если на вашем входе большие непрерывные данные, то простоя прерывание сработает через долгое время, и к тому времени вы могли перезаписать свой буфер. Для этого вы можете использовать другие прерывания DMA, такие как Half Complete и Full Complete. Так что об этом тоже можно позаботиться. Я лично обнаружил, что этот метод глючит во время стресс-тестирования. Но нет причин для этого, у меня не было достаточно времени для его отладки, когда я пытался его использовать, но вы найдете в Интернете статьи об этой технике.

...