Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hardware sync capability to SerialBase #14600

Closed
wants to merge 65 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
8d63828
Add serial_tx_empty API
pennam Apr 22, 2021
069c030
serial_tx_empty TARGET_Ambiq_Micro/TARGET_Apollo3
pennam Apr 22, 2021
970bb55
serial_tx_empty TARGET_Analog_Devices/TARGET_ADUCM302X/
pennam Apr 22, 2021
255b4bc
serial_tx_empty TARGET_Analog_Devices/TARGET_ADUCM4X50
pennam Apr 22, 2021
ef1fa49
serial_tx_empty Target_Freescale TARGET_KL25Z
pennam Apr 22, 2021
1bf5396
serial_tx_empty Target_Freescale TARGET_KL46Z
pennam Apr 22, 2021
0b65964
serial_tx_empty TARGET_Freescale TARGET_K66F
pennam Apr 22, 2021
0ac64d3
serial_tx_empty TARGET_Freescale TARGET_K82F
pennam Apr 22, 2021
db32e05
serial_tx_empty TARGET_Freescale TARGET_KL43Z
pennam Apr 22, 2021
4a413c2
serial_tx_empty TARGET_Freescale TARGET_KW41Z
pennam Apr 22, 2021
5ae1c35
serial_tx_empty TARGET_Freescale TARGET_MCU_K22F
pennam Apr 22, 2021
b669dc9
serial_tx_empty TARGET_Freescale TARGET_MCU_K64F
pennam Apr 22, 2021
f67116c
serial_tx_empty TARGET_GigaDevice/TARGET_GD32F30X
pennam Apr 22, 2021
4c9a34b
serial_tx_empty TARGET_GigaDevice/TARGET_GD32F4XX
pennam Apr 22, 2021
2bc6b86
serial_tx_empty TARGET_Maxim/TARGET_MAX32620C
pennam Apr 22, 2021
f755ad3
serial_tx_empty TARGET_Maxim/TARGET_MAX32625
pennam Apr 22, 2021
77501b3
serial_tx_empty TARGET_Maxim/TARGET_MAX32630
pennam Apr 22, 2021
f0b25da
serial_tx_empty TARGET_NUVOTON/TARGET_M251
pennam Apr 22, 2021
ee0945a
serial_tx_empty TARGET_NUVOTON/TARGET_M261
pennam Apr 22, 2021
8a3bb5a
serial_tx_empty TARGET_NUVOTON/TARGET_M451
pennam Apr 22, 2021
004fb7f
serial_tx_empty TARGET_NUVOTON/TARGET_M480
pennam Apr 22, 2021
c0a4c66
serial_tx_empty TARGET_NUVOTON/TARGET_NANO100
pennam Apr 22, 2021
9f0ea60
serial_tx_empty TARGET_NUVOTON/TARGET_NUC472
pennam Apr 22, 2021
3593d37
serial_tx_empty TARGET_RENESAS/TARGET_RZ_A1XX
pennam Apr 23, 2021
8d4353a
serial_tx_empty TARGET_RENESAS/TARGET_RZ_A2XX
pennam Apr 23, 2021
7e0a4c7
serial_tx_empty TARGET_NRF5x/TARGET_NRF52
pennam Apr 23, 2021
fe43bca
serial_tx_empty TARGET_Cypress/TARGET_PSOC6
pennam Apr 23, 2021
db359b6
serial_tx_empty TARGET_STM
pennam Apr 23, 2021
c82bbef
serial_tx_empty TARGET_NXP/TARGET_LPC11XX_11CXX
pennam Apr 27, 2021
1da87c2
serial_tx_empty TARGET_NXP/TARGET_LPC176X
pennam Apr 27, 2021
3670bb0
serial_tx_empty TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_LPC
pennam Apr 27, 2021
f8da4c6
serial_tx_empty TARGET_Samsung/TARGET_SIDK_S1SBP6A
pennam Apr 27, 2021
465218f
serial_tx_empty TARGET_Silicon_Labs/TARGET_EFM32
pennam Apr 27, 2021
f675e51
serial_tx_empty TARGET_TOSHIBA/TARGET_TMPM46B
pennam Apr 27, 2021
4845616
serial_tx_empty TARGET_TOSHIBA/TARGET_TMPM4G9
pennam Apr 27, 2021
08f7853
serial_tx_empty TARGET_ARM_SSG/TARGET_MUSCA_B1
pennam Apr 27, 2021
5245c1c
serial_tx_empty TARGET_ARM_SSG/TARGET_MUSCA_S1
pennam Apr 27, 2021
4c17121
serial_tx_empty TARGET_Samsung/TARGET_SIDK_S5JS100
pennam Apr 27, 2021
2c491f6
UartBase hardware sync
pennam Apr 19, 2021
fa10ae3
SerialBase fixes and timeout implementation
pennam May 3, 2021
45bac9e
Use sleep_for instead of wait_us
pennam May 3, 2021
4e52fb1
Don't use software timeout if _flow_type == CTS or _flow_type == RTSCTS
pennam May 3, 2021
84eb205
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_M251/
pennam May 3, 2021
9d2236e
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_M261/
pennam May 3, 2021
55243ec
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_M451/
pennam May 3, 2021
5cd61f2
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_M480/
pennam May 3, 2021
1c5f33f
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_NANO100/
pennam May 3, 2021
6cd7063
Fix UART_IS_TX_EMPTY TARGET_NUVOTON/TARGET_NUC472/
pennam May 3, 2021
66ecb29
Fix keep char time allowance in Chrono domain
pennam May 3, 2021
3b7c94c
serial_tx_empty TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1050
pennam May 12, 2021
5aece6b
serial_tx_empty TARGET_NXP/TARGET_MCUXpresso_MCUS/TARGET_MIMXRT1170
pennam May 12, 2021
bdb44e2
Use explicit paths for mbed_chrono and ThisThread
pennam Jun 5, 2021
9141701
Update serial_tx_empty() function description
pennam Jun 5, 2021
6f6b665
Update FileHandle sync() function description
pennam Jun 5, 2021
bf8aa3c
Update SerialBase sync() function description
pennam Jun 5, 2021
97994e3
Increase char_time_allowance maximum counter value because CY8CPROTO_…
pennam Jun 7, 2021
2a15da2
Add testcase to check SerialBase sync capability
pennam Jun 18, 2021
b063b41
Update uart fpga common tests to check also for serial_tx_empty()
pennam Jun 22, 2021
b99ff36
Round up packet transmission time to avoid test failures caused by 1u…
pennam Jun 22, 2021
ac2f4ff
Fix build for TARGET_EFM32GG
pennam Aug 17, 2021
dfa17d1
Fix build for EV_COG_AD3029LZ
pennam Aug 17, 2021
5f8a564
Fix build for MIMXRT1050_EVK
pennam Aug 17, 2021
a566490
Fix build for MIMXRT1170_EVK
pennam Aug 17, 2021
b5c1eef
Fix build for S5JS100
pennam Aug 17, 2021
2b00cf6
Add implementation for TARGET_FVP_MPS2, TARGET_CM3DS_MPS2 and TARGET_…
pennam Aug 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions drivers/include/drivers/SerialBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,14 @@ class SerialBase : private NonCopyable<SerialBase> {
*/
void send_break();

/** Ensures all data stored in peripheral buffers is transmitted to the bus
*
* The function shall block until all the content of peripheral buffers is transmitted.
*
* @return 0 on success, negative error code on failure
*/
int sync();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not call this function flush to better explain what it does?
A sync function could have different meaning, typically ensuring that buffered data is written to the physical device.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this case the description is misleading, the goal of this function is to ensure that all data stored in the tx FIFO or TX register is written to the serial bus. I'll update the description to avoid misunderstandings. Thanks!

Copy link
Contributor

@kjbracey kjbracey May 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The misleading description was inherited from FileHandle.h, which uses the same wording. Could you fix that at the same time?

The intent is to perform the same function as POSIX fsync for files, and we extend that to the serial port. (Apparently POSIX has a separate tcdrain call which does that, and fsync doesn't, but we reuse fsync for simplicity,)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've updatede the functions description here 6f6b665 and here bf8bf69. i hope i've got the correct one.


/** Enable serial input
*
* If both serial input and serial output are disabled, the
Expand Down
6 changes: 6 additions & 0 deletions drivers/include/drivers/UnbufferedSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ class UnbufferedSerial:
return -ESPIPE;
}

/** Flush any buffers associated with the file
*
* @return 0 on success, negative error code on failure
*/
int sync() override;

/** Get the size of the file
*
* @return Size of the file in bytes
Expand Down
2 changes: 1 addition & 1 deletion drivers/source/BufferedSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ int BufferedSerial::sync()

api_unlock();

return 0;
return SerialBase::sync();
}

void BufferedSerial::sigio(Callback<void()> func)
Expand Down
25 changes: 25 additions & 0 deletions drivers/source/SerialBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "platform/mbed_wait_api.h"
#include "platform/mbed_critical.h"
#include "platform/mbed_power_mgmt.h"
#include "platform/mbed_chrono.h"
#include "rtos/ThisThread.h"

#if DEVICE_SERIAL

Expand Down Expand Up @@ -164,6 +166,29 @@ void SerialBase::_deinit()
serial_free(&_serial);
}

int SerialBase::sync()
{
int count = 0;
// See send_break(), ensure at least 1ms sleep time
auto char_time_allowance = chrono::milliseconds_u32((18000 / _baud) + 1);
lock();
// Assuming the biggest Tx FIFO of 128 bytes (as for CY8CPROTO_062_4343W)
while ((!serial_tx_empty(&_serial)) && (count < 128)) {
rtos::ThisThread::sleep_for(char_time_allowance);
#if DEVICE_SERIAL_FC
if ((_flow_type == RTS) || (_flow_type == Disabled))
#endif
count++;
}
unlock();

if (count < 128) {
return 0;
} else {
return -ETIME;
}
}

void SerialBase::enable_input(bool enable)
{
lock();
Expand Down
5 changes: 5 additions & 0 deletions drivers/source/UnbufferedSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ short UnbufferedSerial::poll(short events) const
return revents;
}

int UnbufferedSerial::sync()
{
return SerialBase::sync();
}

int UnbufferedSerial::enable_input(bool enabled)
{
SerialBase::enable_input(enabled);
Expand Down
6 changes: 6 additions & 0 deletions drivers/tests/TESTS/host_tests/serial_comms.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@


MSG_KEY_ECHO_MESSAGE = "echo_message"
MSG_KEY_SYNC_MESSAGE = "sync_message"


class SerialComms(BaseHostTest):
Expand All @@ -32,7 +33,12 @@ def __init__(self):
def setup(self):
"""Register call backs to handle message from the target."""
self.register_callback(MSG_KEY_ECHO_MESSAGE, self.cb_echo_message)
self.register_callback(MSG_KEY_SYNC_MESSAGE, self.cb_sync_message)

def cb_echo_message(self, key, value, timestamp):
"""Send back the key and value received."""
self.send_kv(key, value)

def cb_sync_message(self, key, value, timestamp):
"""Test completed."""
self.notify_complete(True)
13 changes: 13 additions & 0 deletions drivers/tests/TESTS/mbed_drivers/sync_serial/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Copyright (c) 2020 ARM Limited. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR)

set(MBED_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../../.. CACHE INTERNAL "")
set(TEST_TARGET mbed-drivers-sync-serial)

include(${MBED_PATH}/tools/cmake/mbed_greentea.cmake)

project(${TEST_TARGET})

mbed_greentea_add_test(TEST_NAME ${TEST_TARGET})
99 changes: 99 additions & 0 deletions drivers/tests/TESTS/mbed_drivers/sync_serial/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* Copyright (c) 2019 Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !DEVICE_SERIAL
#error [NOT_SUPPORTED] serial communication not supported for this target
#else

#include "mbed.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "platform/FileHandle.h"
#include "drivers/BufferedSerial.h"


using namespace utest::v1;


/**
* Macros for setting console flow control.
*/
#define CONSOLE_FLOWCONTROL_RTS 1
#define CONSOLE_FLOWCONTROL_CTS 2
#define CONSOLE_FLOWCONTROL_RTSCTS 3
#define mbed_console_concat_(x) CONSOLE_FLOWCONTROL_##x
#define mbed_console_concat(x) mbed_console_concat_(x)
#define CONSOLE_FLOWCONTROL mbed_console_concat(MBED_CONF_TARGET_CONSOLE_UART_FLOW_CONTROL)


#define MSG_KEY_SYNC_MESSAGE "sync_message"
#define MSG_VALUE_HELLO_WORLD "Hello, world!"


#define EXPECTED_SYNCED_STRING "{{" MSG_KEY_SYNC_MESSAGE ";" MSG_VALUE_HELLO_WORLD "}}"
// The target is expected to transmit Greentea messages with \n (or \r\n) or they are not detected by the host
#define SYNC_STRING_TO_SEND EXPECTED_SYNCED_STRING "\n"


static BufferedSerial buffered_serial_obj(
CONSOLE_TX, CONSOLE_RX, MBED_CONF_PLATFORM_STDIO_BAUD_RATE
);


FileHandle *mbed::mbed_override_console(int fd)
{
return &buffered_serial_obj;
}


static void test_serial_sync()
{
char tx_msg[] = SYNC_STRING_TO_SEND;

TEST_ASSERT_EQUAL_UINT(
strlen(tx_msg) + 1,
buffered_serial_obj.write(tx_msg, strlen(tx_msg) + 1)
);

// Wait the message is completely sent to the bus
buffered_serial_obj.sync();
system_reset();
TEST_ASSERT_MESSAGE(0, "The device did not reset as expected.");
}


int main()
{
#if CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTS
buffered_serial_obj.set_flow_control(
SerialBase::RTS, STDIO_UART_RTS, NC
);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_CTS
buffered_serial_obj.set_flow_control(
SerialBase::CTS, NC, STDIO_UART_CTS
);
#elif CONSOLE_FLOWCONTROL == CONSOLE_FLOWCONTROL_RTSCTS
buffered_serial_obj.set_flow_control(
SerialBase::RTSCTS, STDIO_UART_RTS, STDIO_UART_CTS
);
#endif
GREENTEA_SETUP(12, "serial_comms");
test_serial_sync(); // The result of this test suite is reported by the host side.
GREENTEA_TESTSUITE_RESULT(0); // Fail on any error.
}

#endif // !DEVICE_SERIAL
8 changes: 8 additions & 0 deletions hal/include/hal/serial_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,14 @@ int serial_readable(serial_t *obj);
*/
int serial_writable(serial_t *obj);

/** Check if the serial peripheral tx buffer or tx FIFO is empty and the last byte has
* been completely transmitted from the shift register to the bus.
*
* @param obj The serial object
* @return Non-zero value if tx is empty, 0 otherwise.
*/
int serial_tx_empty(serial_t *obj);

/** Clear the serial peripheral
*
* @param obj The serial object
Expand Down
14 changes: 9 additions & 5 deletions hal/tests/TESTS/mbed_hal_fpga_ci_test_shield/uart/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ static void uart_test_common(int baudrate, int data_bits, SerialParity parity, i

// start_bit + data_bits + parity_bit + stop_bits
int packet_bits = 1 + data_bits + stop_bits + (parity == ParityNone ? 0 : 1);
us_timestamp_t packet_tx_time = 1000000 * packet_bits / baudrate;
us_timestamp_t packet_tx_time = (1000000 * packet_bits / baudrate) + 0.5;
const ticker_data_t *const us_ticker = get_us_ticker_data();

bool use_flow_control = (cts != NC && rts != NC) ? true : false;
Expand Down Expand Up @@ -211,10 +211,12 @@ static void uart_test_common(int baudrate, int data_bits, SerialParity parity, i
checksum += tx_val;
serial_putc(&serial, tx_val);
us_timestamp_t end_ts = ticker_read_us(us_ticker) + 2 * packet_tx_time;
while (tester.rx_get_count() != reps && ticker_read_us(us_ticker) <= end_ts) {
while ((!serial_tx_empty(&serial) || tester.rx_get_count() != reps) && ticker_read_us(us_ticker) <= end_ts) {
// Wait (no longer than twice the time of one packet transfer) for
// the DUT to send all buffered data to the bus and for
// the FPGA to receive data and update the byte counter.
}
TEST_ASSERT_EQUAL(1, serial_tx_empty(&serial));
TEST_ASSERT_EQUAL_UINT32(reps, tester.rx_get_count());
TEST_ASSERT_EQUAL(0, tester.rx_get_parity_errors());
TEST_ASSERT_EQUAL(0, tester.rx_get_stop_errors());
Expand Down Expand Up @@ -265,10 +267,12 @@ static void uart_test_common(int baudrate, int data_bits, SerialParity parity, i
serial_irq_set(&serial, TxIrq, 0);
core_util_critical_section_exit();
us_timestamp_t end_ts = ticker_read_us(us_ticker) + 2 * packet_tx_time;
while (ticker_read_us(us_ticker) <= end_ts) {
// Wait twice the time of one packet transfer for the FPGA
// to receive and process data.
while (!serial_tx_empty(&serial) && ticker_read_us(us_ticker) <= end_ts) {
// Wait (no longer than twice the time of one packet transfer) for
// the DUT to send all buffered data to the bus and for
// the FPGA to receive and process data.
};
TEST_ASSERT_EQUAL(1, serial_tx_empty(&serial));
tester.rx_stop();
TEST_ASSERT_EQUAL_UINT32(2 * PUTC_REPS, tester.rx_get_count());
TEST_ASSERT_EQUAL(0, tester.rx_get_parity_errors());
Expand Down
2 changes: 1 addition & 1 deletion platform/include/platform/FileHandle.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class FileHandle : private NonCopyable<FileHandle> {
*/
virtual int close() = 0;

/** Flush any buffers associated with the file
/** Synchronize the contents of a file with storage device
*
* @return 0 on success, negative error code on failure
*/
Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_FM/TARGET_FVP_MPS2/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,11 @@ int serial_writable(serial_t *obj)
return !(obj->uart->STATE & 0x1);
}

int serial_tx_empty(serial_t *obj)
{
return !(obj->uart->STATE & 0x1);
}

void serial_clear(serial_t *obj)
{
obj->uart->DATA = 0x00;
Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_CM3DS_MPS2/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,11 @@ int serial_writable(serial_t *obj)
return arm_uart_tx_ready(obj->uart);
}

int serial_tx_empty(serial_t *obj)
{
return arm_uart_tx_ready(obj->uart);
}

void serial_clear(serial_t *obj)
{
(void)arm_uart_write(obj->uart, 0x00);
Expand Down
4 changes: 4 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MPS2/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,10 @@ int serial_writable(serial_t *obj) {
return obj->uart->STATE & 0x1;
}

int serial_tx_empty(serial_t *obj) {
return obj->uart->STATE & 0x1;
}

void serial_clear(serial_t *obj) {
obj->uart->DATA = 0x00;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ struct _uart_pl011_reg_map_t {
0x1u<<UART_PL011_UARTFR_RX_FIFO_EMPTY_OFF)
#define UART_PL011_UARTFR_TX_FIFO_FULL ( \
0x1u<<UART_PL011_UARTFR_TX_FIFO_FULL_OFF)
#define UART_PL011_UARTFR_TX_FIFO_EMPTY ( \
0x1u<<UART_PL011_UARTFR_TX_FIFO_EMPTY_OFF)
#define UART_PL011_UARTFR_RI_MASK ( \
0x1u<<UART_PL011_UARTFR_RI_OFF)

Expand Down Expand Up @@ -636,6 +638,21 @@ bool uart_pl011_is_writable(struct uart_pl011_dev_t* dev)

}

bool uart_pl011_is_tx_empty(struct uart_pl011_dev_t* dev)
{
struct _uart_pl011_reg_map_t* p_uart =
(struct _uart_pl011_reg_map_t*)dev->cfg->base;

if( ((p_uart->uartfr & UART_PL011_UARTFR_TX_FIFO_EMPTY) == 1) &&
/* Transmit Fifo is empty */
((p_uart->uartfr & UART_PL011_UARTFR_BUSYBIT) == 0)) {
/* Tx is not BUSY */
return true;
}
return false;

}

void uart_pl011_write(struct uart_pl011_dev_t* dev, uint8_t byte)
{
struct _uart_pl011_reg_map_t* p_uart =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,17 @@ enum uart_pl011_error_t uart_pl011_read(struct uart_pl011_dev_t* dev,
*/
bool uart_pl011_is_writable(struct uart_pl011_dev_t* dev);

/**
* \brief Check if the UART tx buffer is empty
*
* \param[in] dev UART device struct \ref uart_pl011_dev_t
*
* \return Returns bool, true if UART is tx buffer is empty, false otherwise
*
* \note This function doesn't check if dev is NULL.
*/
bool uart_pl011_is_tx_empty(struct uart_pl011_dev_t* dev);

/**
* \brief Writes a byte to UART dev.
*
Expand Down
5 changes: 5 additions & 0 deletions targets/TARGET_ARM_SSG/TARGET_MUSCA_B1/serial_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,11 @@ int serial_writable(serial_t *obj)
return (int)uart_pl011_is_writable(obj->uart_dev);
}

int serial_tx_empty(serial_t *obj)
{
return (int)uart_pl011_is_tx_empty(obj->uart_dev);
}

int serial_getc(serial_t *obj)
{
uint8_t byte = 0;
Expand Down
Loading