Как сбросить состояние драйвера HAL UART (HAL) STM32? - PullRequest
1 голос
/ 28 марта 2019

Я знаю, что можно включить прерывание приема UART, используя

HAL_UART_Receive_IT(&huart2, (uint8_t *)rx_buffer, expectedNumberOfBytes)
  • Но как только он начался, как его остановить, "вручную"?

Мы можем отключить прерывание UART, используя HAL_NVIC_DisableIRQ() (например: HAL_NVIC_DisableIRQ(USART1_IRQn)). Это предотвратит возникновение прерывания, но состояние, установленное функцией HAL_UART_Receive_IT, равной HAL_UART_STATE_BUSY_RX, необходимо установить обратно на HAL_UART_STATE_READY, чтобы дескриптор uart мог вернуться в состояние, которое может принять новый HAL_UART_Receive_IT() Звоните.

Вопрос
Как мне сбросить состояние прерывания UART, если я хочу через некоторое время отключить прерывание Rx?

Вопросы переполнения стека не касаются того, как сбросить состояние; Я сослался на эти вопросы:

  1. Отключение прерывания в обработчике прерываний STM32F407
  2. https://electronics.stackexchange.com/questions/100073/stm32-usart-rx-interrupts

Я мог бы использовать USART_ClearITPendingBit() или USART_ITConfig(), но они определены как частные функции библиотекой HAL STM. Так я должен их использовать?

Ответы [ 2 ]

3 голосов
/ 29 марта 2019

Как [сделать] сбросить состояние прерывания UART, если [I] хочет через некоторое время отключить прерывание Rx [?]

(см. Его использование в " stm32f4xx_hal_uart.c", например.)

Член huart->RxState структуры дескриптора uart действительно используется только библиотекой HAL для внутренних целей при выполнении таких операций, как HAL_UART_Receive(), HAL_UART_Receive_IT(), HAL_UART_Receive_DMA(), (и многие другие внутренние функции, подобные этой) и т. Д. Если вы вручную реализуете свои собственные вызовы UART Tx и Rx на основе прерываний и кольцевого буфера, однако, , который является предпочтительным способомсделайте это , этот член абсолютно бессмысленный и не имеет значения, что вы с ним делаете, так как он используется только внутри вызовов функций библиотеки HAL и обработчиков HAL ISR (ни один из которых вам не нужно использовать), и действительно имеетне имеет ничего общего с прерываниями уровня регистра и другими вещами напрямую.

Копаясь вокруг исходного кода в stm32f4xx_hal_uart.c (например), однако, вот пара допустимых опций, которые вы можетеПрименение:

1.Как сбросить huart->RxState на HAL_UART_STATE_READY:

  1. Звонить HAL_UART_Init().Изучив его исходный код, вы увидите, что он вызывает huart->RxState= HAL_UART_STATE_READY; перед возвратом.
  2. Просто вручную установите huart->RxState = HAL_UART_STATE_READY; Пока вы знаете, что правильно остановили получение на основе прерываний в середине его обработки, это совершенно верно.

Давайте продолжим, однако.

Представьте, что вы используете UART7 на STM32F4.Следовательно, в вашем файле обработчика прерываний stm32f4xx_it.c вы увидите следующий код, автоматически сгенерированный STM32CubeMX:

/**
* @brief This function handles UART7 global interrupt.
*/
void UART7_IRQHandler(void)
{
  /* USER CODE BEGIN UART7_IRQn 0 */

  /* USER CODE END UART7_IRQn 0 */
  HAL_UART_IRQHandler(&huart7);
  /* USER CODE BEGIN UART7_IRQn 1 */

  /* USER CODE END UART7_IRQn 1 */
}

Давайте рассмотрим несколько уровней отключения / включения прерываний.

2.От самого широкого до самого узкого диапазона, есть несколько способов отключить / включить прерывание USART Rx:

  1. Вы можете отключить / включить ВСЕ прерывания, включая это UART7_IRQHandler(), используя это ядро ​​ARMCMSIS вызывает:

    __disable_irq();
    __enable_irq();
    

    Источник: https://stm32f4 -discovery.net / 2015/06 / как правильно правильно включить-прерывать-в-руке-кортекс-м /

    Итак, вы можете сделать следующее, чтобы отключить прерывание, сбросить RxState, а затем снова запустить прием на основе прерываний, когда будете готовы:

    __disable_irq();
    huart7->RxState= HAL_UART_STATE_READY;
    
    __enable_irq();
    HAL_UART_Receive_IT(&huart7, (uint8_t *)rx_buffer, expectedNumberOfBytes);
    
  2. Вы можете отключить / включить ТОЛЬКО прерывания UART7_IRQHandler() (все 10 типов прерываний uart7, связанных с этим вектором прерываний, включая связанные с Tx, связанные с Rx, связанные с ошибками и т. Д.), Используя эти вызовы STM32 HAL:

    HAL_NVIC_DisableIRQ(UART7_IRQn);
    HAL_NVIC_EnableIRQ(UART7_IRQn);
    

    Затем сделайте то же самое, что и выше, за исключением того, что вместо этого используйте эти вызовы для отключения / включения прерываний.

  3. Если вы углубитесь в реализацию HAL_UART_IRQHandler()однако, который вызывается UART7_IRQHandler(), вы увидите, что он вызывает только прерываниеоснованный на t обработчик приема, UART_Receive_IT(), если оба бита USART_SR_RXNE («Получение не пусто» внутри регистра состояния USART) и бит USART_CR1_RXNEIE («Разрешение прерывания приема не пусто», внутри регистра управления USART1), оба установлены.Бит RXNE устанавливается каждый раз, когда поступает байт, и очищается всякий раз, когда вы читаете регистр данных или записываете в него ноль. Бит включения прерывания - это то, что вы имеете полный контроль над отключением этого прерывания приема UART, и если вы сбросите этот бит вручную, вы отключите приемное прерывание, отключив любые другие типы прерываний, связанных с этим USART.Это лучший способ сделать это, поскольку с этим UART связано 10 источников прерываний. Другими словами, очистка этого бита не только приводит к сбою проверки внутри HAL_UART_IRQHandler(), но и предотвращает прерывание приема.происходит в первую очередь!См. Справочное руководство RM0090 Ред. 16 , например:

    p969: enter image description here

    p1009: enter image description here

    p1011: enter image description here

    p1015: enter image description here

    p1013: enter image description here

    Таким образом, чтобы отключить / включить только прерывание приема не пустой USART, выполните следующие действия. См. Регистр управления (USART_CR1) на p1013, показанный чуть выше.

    // Disable the USART Receive Not Empty interrupt
    CLEAR_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
    
    // Enable the USART Receive Not Empty interrupt
    SET_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
    

    Теперь вы можете сделать следующее, чтобы отключить прерывание приема USART, сбросить HAL RxState, а затем снова запустить прием на основе прерываний, когда будете готовы:

    CLEAR_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE);
    huart7->RxState= HAL_UART_STATE_READY;
    
    SET_BIT(huart7.Instance.CR1, USART_CR1_RXNEIE); // This call isn't actually necessary, as this bit is set inside `HAL_UART_Receive_IT()` as well
    HAL_UART_Receive_IT(&huart7, (uint8_t *)rx_buffer, expectedNumberOfBytes);
    

3. Как (неловко) использовать HAL_UART_Receive_IT() для непрерывного приема на основе прерываний.

TODO

4. Почему, в конце концов, HAL_UART_Receive_IT() действительно не очень полезная функция.

TODO

5. Как вручную настроить собственные ISR Tx и Rx на основе прерываний и функций.

TODO

0 голосов
/ 28 марта 2019

Большинство UART сбрасывают любые ожидающие прерывания получения, когда программа читает из регистра хранения.Поэтому мой ответ будет таким: просто прочитайте регистр данных после отключения прерываний и проигнорируйте результат.

У меня еще не было возможности попробовать это на моем STM32, но ...

...