2 years, 7 months ago.

Readable()/Writable(): Serial Class Question

I am currently working with the Serial class, and in doing so I found myself in a predicament. Although readable() returns if there are any characters left in the buffer, writable() returns whether there is any space left in the buffer. In my code, I need a way to ensure that the write buffer is empty, which you can't do (to my knowledge )with writable(). Does anyone have a way to do this?

1 Answer

2 years, 7 months ago.

There are two options, neither of which are ideal:

1) Use the Tx interrupt. This will generate an interrupt when transmission is complete. You can then use that interrupt to set a flag. Your code can then check that flag rather than calling writeable(). You would need to remember to clear the flag every time you write data to the serial port.

Also on an STM-F7 platform using mbed-os I had to make a small change to the library to get the Tx interrupt to work correctly but that was an old version of the library, it may have been fixed by now. I don't know if other STM parts would be similar or not.

2) Check the transmitter empty status bit of the UART control register. For a single uart on a single platform you could do this by checking the registers directly. If you want flexibility that would require you to either define your own serial class that inherits the mbed one or modifications to the mbed library to add the feature.


Changes to library in targets/TARGET_STM/TARGET_STM32F7/serial_device.c/

I added some code on a TX interrupt to read and set/clear some bits. This was long enough ago that I can't remember the logic behind it, I seem to remember thinking at the time that it was a horrible hack but it got things working and this wasn't for production code so I didn't spend any more time on it.

static void uart_irq(int id)
    UART_HandleTypeDef * huart = &uart_handlers[id];
    if (serial_irq_ids[id] != 0) {
        if (__HAL_UART_GET_FLAG(huart, UART_FLAG_TXE) != RESET) {
            if (__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) {
                if (READ_REG(huart->Instance->CR1) && USART_CR1_TXEIE) {
                    CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
                    SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
                huart->Instance->ICR = USART_ICR_TCCF;

// rest of function...

Accepted Answer

I also was reading over the weekend that the sync and fsync functions work very well for my purpose. I'll try your suggestions and see how they go. Thank you!

posted by Benjamin Spooner 30 Jul 2018