В регистре CR1 активирую бит IDLEIE.
Это активация прерываний по событию отправки пакета данных.
Потом отправляю через терминал СОМ порта символы.
Вижу в Keil как флаг IDLE в регистре SR активируется.
Но прерывание не срабатывает, почему?
Прерывания активированы.
Есть 9 UART Callback функций, ни одна из них не срабатывает.
HAL_UART_TxCpltCallback
HAL_UART_TxHalfCpltCallback
HAL_UART_RxCpltCallback
HAL_UART_RxHalfCpltCallback
HAL_UART_ErrorCallback
HAL_UART_AbortCpltCallback
HAL_UART_AbortTransmitCpltCallback
HAL_UART_AbortReceiveCpltCallback
HAL_UARTEx_RxEventCallback
-----------------------------------------------------------------
HAL_UARTEx_RxEventCallback начинает срабатывать только тогда, когда в код добавляю это HAL_UARTEx_ReceiveToIdle_IT(&huart4, data, 5);
Какие настройки нужны для того, чтоб отрабатывал каллбек при активации флага IDLE в регистре SR?
Одна из этих настроек это активация бита IDLEIE в регистре CR1. Но видимо этого недостаточно.
Мне казалось только эта настройка нужна.
п.с. Скорость передачи по УАРТ правильная.
Посмотри внутри HAL_UARTEx_ReceiveToIdle_IT(), какие биты выставляются, раз при ее вызове callback срабатывает.
Здесь UART_Start_Receive_IT активируется бит разрешающий прерывания по RXNE.
Здесь
__HAL_UART_CLEAR_IDLEFLAG(huart); ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
очищается и ставится бит разрешающий прерывания по IDLE.
Больше ничего я там не нашёл.
Чётность у меня отключена, прерывания по ней соответственно тоже.
--------------------------------
Может дело не в HAL_UARTEx_ReceiveToIdle_IT функции, а в том месте, откуда HAL_UARTEx_RxEventCallback вызывается.
Функция HAL_UARTEx_RxEventCallback вызывается из HAL_UART_IRQHandler(&huart3);
if ((huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE) && ((isrflags & USART_SR_IDLE) != 0U) && ((cr1its & USART_SR_IDLE) != 0U)) { __HAL_UART_CLEAR_IDLEFLAG(huart);. }
В переводе на CMSIS здесь написано это:
if (USART3->CR1&USART_CR1_IDLEIE && USART3->SR&USART_SR_IDLE) { USART3->CR1&=~(USART_CR1_IDLEIE); }
Кароче идёт какое то хитрое включение выключение IDLEIE бита в обоих функциях.
Надо разбираться. Такую же ситуацию в коде я создать не смог.
Нет.
Думаю я ошибся насчёт __HAL_UART_CLEAR_IDLEFLAG(huart);
-------------------------------------------------------------------
An interrupt is generated if the IDLEIE=1 in the USART_CR1 register. It is cleared by a software sequence (an read to the USART_SR register followed by a read to the USART_DR register).
Кароче надо разобраться как очищать бит IDLE в SR регистре.
It is cleared by a software sequence (an read to the USART_SR register followed by a read to the USART_DR register).
Да, чтоб очистить IDLE бит, надо сначала прочитать SR регистр, а потом DR регистр.
uint32_t dr=0; uint32_t sr=0; if (USART3->CR1&USART_CR1_IDLEIE && USART3->SR&USART_SR_IDLE) { sr=USART3->SR; dr=USART3->DR; }
Но проблему это не решило. Каллбек не вызывается.
Только если у Вас есть очень много свободного времени.
Я для себя нашёл объяснение, не подтверждённое, но мне сейчас достаточно.
Думаю есть какая то переменная, булевая или какая то ещё, в функции HAL_UARTEx_ReceiveToIdle_IT, которая обнуляется при вызове HAL_UARTEx_RxEventCallback.
И для того чтоб вызвать HAL_UARTEx_RxEventCallback снова, надо опять вызвать функцию HAL_UARTEx_ReceiveToIdle_IT.
Потому что дело точно не только во флагах и настройке битов.
Настройка функции HAL_UARTEx_ReceiveToIdle_IT производится конечно по флагам и битам, но внутри этой функции тоже что то меняется, что влияет на вызов Каллбека.
Проект несложный:
Дело именно в отработке функции HAL_UARTEx_ReceiveToIdle_IT.
Функция HAL_UARTEx_ReceiveToIdle_IT отработала, Каллбек вызовется, функция HAL_UARTEx_ReceiveToIdle_IT не отработала, Каллбек не вызовется.
@stm Ну я и говорю, суть в коде внутри HAL_UARTEx_ReceiveToIdle_IT(). Я очень бегло пробежался, чтобы колбэк HAL_UARTEx_RxEventCallback() в принципе имел хоть какие-то шансы на выполнение, в huart->ReceptionType должно быть HAL_UART_RECEPTION_TOIDLE. Вот самый первый и очевидный маркер, почему вызов может не происходить.
UART Регистры настраивает структура USART_TypeDef *Instance;
находящаяся в UART_HandleTypeDef;
Что настраивают остальные переменные, находящися в UART_HandleTypeDef ?
Вот они:
UART_InitTypeDef Init;
const uint8_t *pTxBuffPtr;
uint16_t TxXferSize;
__IO uint16_t TxXferCount;
uint8_t *pRxBuffPtr;
uint16_t RxXferSize;
__IO uint16_t RxXferCount;
__IO HAL_UART_RxTypeTypeDef ReceptionType;
DMA_HandleTypeDef *hdmatx;
DMA_HandleTypeDef *hdmarx;
HAL_LockTypeDef Lock;
__IO HAL_UART_StateTypeDef gState;
__IO HAL_UART_StateTypeDef RxState;
__IO uint32_t ErrorCode;
Или между периферийными устройствами есть место, где просто можно хранить информацию?
То есть разве есть регистры по этим адресам?
Например регистры USART3 начинаются с адреса 0x4000 4800
А заканчиваются адресом 0x4000 481C.
Так вот то что выше написано, сохраняется после этого адреса 0x4000 481C
huart->ReceptionType
находится в этом же списке. Поэтому спрашиваю.
Эти поля структиры хранятся в пределах адресов, предназначенных для USART3
0x4000 4800 - 0x4000 4BFF
Между этих адресов есть только 7 регистров (SR;DR;BRR;CR1;CR2;CR3;GTPR;)?
А остальное место это просто пространство, где можно хранить любую информацию?
@stm Это адресное пространство отведено под периферию. Там нет ОЗУ. Даже, если в адресации есть разрыв, там нет ничего, что могло бы хранить информацию.