USART3_IRQHandler () постоянно вызывается с набором LL_USART_IsActiveFlag_TXE - PullRequest
0 голосов
/ 18 марта 2020

Я хочу разработать свой собственный последовательный код (а не использовать HAL CubeMX) для взаимодействия с существующей кодовой базой протокола, которая нуждается в низкоуровневых последовательных функциях.

USART3_IRQHandler() вызывается неоднократно (и, следовательно, serial::serial_irq_handler() тоже.

/**
  * @brief This function handles USART3 global interrupt.
  */
void USART3_IRQHandler(void)
{
  /* USER CODE BEGIN USART3_IRQn 0 */
  serial_irq_handler(&usart3);
  /* USER CODE END USART3_IRQn 0 */
  /* USER CODE BEGIN USART3_IRQn 1 */

  /* USER CODE END USART3_IRQn 1 */
}

serial. c:

/**
 * @brief Should be called only by UART/USARTx_IRQHandler()
 */
void serial_irq_handler(struct serial *serial)
{
    // "while" is used in case we decide to turn on the limited FIFOs (USARTs only).
    while (LL_USART_IsActiveFlag_RXNE(serial->usart)) {
        uint8_t b = LL_USART_ReceiveData8(serial->usart);
        circbuf_push(&serial->rxcircbuf, b);
    }

    if (LL_USART_IsActiveFlag_TXE(serial->usart)) {
        LL_USART_ClearFlag_TC(serial->usart);
        serial->txbusy = 0;
    }
}

(serial->usart == USART3 в коде выше.)

Я думаю, что проблема в что я сбрасываю неправильный флаг (T C вместо TXE).

Это причина проблемы?

Я не могу очистить TXE, поскольку LL_USART_ClearFlag_TXE() не существует.

Если я закомментирую LL_USART_EnableIT_TXE(serial->usart); в коде инициализации, проблема исчезнет (но тогда я не смогу увидеть, свободен ли последовательный порт для записи).

Ответы [ 2 ]

1 голос
/ 18 марта 2020

Неправильный лог c.

Прерывание TXE должно быть включено только , если у вас есть данные для отправки.

Когда вы закончите sh подачу регистра данных - вы отключите его.

Логично, что флаг сброса TXE отсутствует. Флаг EMPTY можно сбросить, только сделав его не пустым

, но тогда я не могу увидеть, свободен ли последовательный порт для записи в

Вам необходимо реализовать буфер. И проверьте, есть ли в буфере место для размещения новых данных для отправки.

0 голосов
/ 18 марта 2020

У меня были неправильные логики c, как указал P__J __.

Новый код выглядит следующим образом и работает.

serial. c:

int serial_tx(struct serial *serial, uint8_t byte) {
    if (serial->txbusy) {
        serial->stats.txbusy++;
        return -1;
    }
    serial->txbusy = 1;
    LL_USART_TransmitData8(serial->usart, byte);
    LL_USART_EnableIT_TXE(serial->usart);
    serial->stats.txbytes++;
    return 0;
}

int serial_rx(struct serial *serial, uint8_t *out) {
    return circbuf_pop(&serial->rxcircbuf, out);
}

/*
 * @brief Should be called only by void UART/USARTx_IRQHandler()
 */
void serial_irq_handler(struct serial *serial)
{
    // while is used in case we decide to turn on the limited FIFOs (USARTs only).
    while (LL_USART_IsActiveFlag_RXNE(serial->usart)) {
        uint8_t b = LL_USART_ReceiveData8(serial->usart);
        circbuf_push(&serial->rxcircbuf, b);
    }

    if (LL_USART_IsActiveFlag_TXE(serial->usart)) {
        LL_USART_DisableIT_TXE(serial->usart);
        serial->txbusy = 0;
    }
}

Мне пришлось реализовать байтовый ввод-вывод, а не буферизацию, как то, что требовалось для более высоких (уже существующих) слоев связи.

- Обновление -

Небольшие изменения в этом коде не работают. Я пытался задействовать флаг TX C, прежде чем дать ссылку на 3000 страниц руководства для этого чипа. Глава 48 содержит данные USART.

https://www.st.com/resource/en/reference_manual/dm00314099-stm32h742-stm32h743-753-and-stm32h750-value-line-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

...