cancel
Showing results for 
Search instead for 
Did you mean: 

printf with HAL_UART_Transmit_IT?

toby2
Senior
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
30 REPLIES 30
Posted on March 31, 2017 at 15:41

I think I might have just realised what your problem is.

You want to use HAL_UART_Transmit_IT() in

sci1_printf() but you cannot if HAL is already transmitting data, ie it returns HAL_BUSY?

Am I correct?

In which case you need to decide if you will just block and wait for the tx to be ready or queue the data for sending later by the callback function, either way the state of the TX needs checking in printf()

Alternatively you can make your life much easier but ignoring HAL and writing your own interrupt routine using a circular buffer, as I suggested in my first post