Там же ж где-то может быть HAL_UART_GetState(&huart_n); и тогда предполагается что-то типа
uint8_t msg[] = "Hello world\n";
HAL_UART_Transmit_IT(&huart1, msg, strlen(msg));
uint8_t state;
state = HAL_UART_GetState(&huart1);
while( (state == HAL_UART_STATE_BUSY_TX) || (state == HAL_UART_STATE_BUSY_TX_RX) ){
//здесь делается что-то полезное
state = HAL_UART_GetState(&huart1);
}
Обработчики пишу сам, эти чудеса никогда не использовал. Но не вижу особой крамолы. У меня в зависимости от лени/требований к функционалу/производительности чего только там нет. Но если использую обращения к голым регистрам, то пишу обертки а-ля LL, тем более между ядрами/семействами/версиями HAL-LL-CMSIS всегда находятся какие-нибудь уродские несовместимости.