Question
printf with HAL_UART_Transmit_IT?
Posted on November 09, 2016 at 10:34
I am new to the hal libraries (but not stm32 devices) and struggle to see howHAL_UART_Transmit_IT is expected to be used for something simple like printf over uart.
Take a blocking example:void PRINT_MESG_UART(const char * format, ... )
{
va_list ap;
uint8_t buffer [128];
int n;
va_start(ap, format);
n = vsnprintf ((char*)buffer, 128, format, ap);
va_end(ap);
//notify_uart(buffer, n);
if(HAL_UART_Transmit(&UartHandle, (uint8_t*)buffer, n, 300) != HAL_OK) {
Error_Handler();
}
} That works fine.
But what if I want it non blocking under interrupts?
What I have come up with is as follows:
uint8_t buffer [128];
void PRINT_MESG_UART(const char * format, ... )
{
va_list ap;
int n;
while (UartHandle.gState != HAL_UART_STATE_READY)
; // will overwrite the buffer otherwise, (needs a timeout and error handling)
va_start(ap, format);
n = vsnprintf ((char*)buffer, 128, format, ap);
va_end(ap);
HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)buffer, n) == HAL_BUSY) ;
} This works, but is pretty poor as it still blocks if the buffer is already in use.
Is there a better way? The obvious way is to use the traditional method of a circular buffer. eg
bool u_put_byte(uint8_t data)
{
bool ok = FALSE;
if ((uart_buffer.txin + 1) % S_BUF_SIZE != uart_buffer.txout)
{
uart_buffer.txbuf[uart_buffer.txin] = data;
uart_buffer.txin = (uart_buffer.txin + 1) % S_BUF_SIZE;
ok = TRUE;
}
SET_BIT(UartHandle.Instance->CR1, USART_CR1_TXEIE);
return ok;
}
void PRINT_MESG_UART(const char * format, ... )
{
va_list ap;
uint8_t buffer[S_BUF_SIZE];
int n;
va_start(ap, format);
n = vsnprintf ((char*)buffer, S_BUF_SIZE, format, ap);
va_end(ap);
int i = 0;
while ((buffer[i] != 0) && (i < S_BUF_SIZE) && (i < n))
{
while (!u_put_byte(buffer[i])) // keep attempting until it succeeds
; // timeout and error handling here.
i++;
}
} However the HAL uart library functions do not appear to support this sort of buffer. Am I correct?
#nucleo #stm32 #hal #uart