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

UART framing API #24335

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
64 changes: 63 additions & 1 deletion libraries/AP_HAL/UARTDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,47 @@ void AP_HAL::UARTDriver::begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace
// silently fail
return;
}
return _begin(baud, rxSpace, txSpace);
_begin(baud, rxSpace, txSpace);
}

void AP_HAL::UARTDriver::begin(uint32_t baud)
{
return begin(baud, 0, 0);
}

/*
begin in frame-based mode. the framing API works on top of the
existing UART infrastructure and framing can be started at any
time after the UART has been started. Consumed frames can be at most frame_size
bytes long, frames longer than this will be considered corrupt and the
framing buffer will be reset. The framing buffer holds at most
frames_in_buffer frames, the frames are stored in a ring buffer and so
older frames that have not been read will be overwritten.
Returns true if the framing API could be started, false otherwise
*/
bool AP_HAL::UARTDriver::begin_framing(uint16_t max_frame_size)
{
if (lock_write_key != 0) {
// silently fail
return false;
}

const bool ret = _begin_framing(max_frame_size);
frame_size = max_frame_size;
return ret;
}

void AP_HAL::UARTDriver::end_framing()
{
if (lock_write_key != 0) {
// silently fail
return;
}

_end_framing();
frame_size = 1;
}

/*
lock the uart for exclusive use by write_locked() and read_locked() with the right key
*/
Expand Down Expand Up @@ -111,6 +144,27 @@ bool AP_HAL::UARTDriver::read(uint8_t &b)
return n > 0;
}

/*
frame-based read. An entire frame will be read into buffer. count indicates the size of the
buffer and if this is less than the size of the frame to be read, the remaining bytes in the frame will
be discarded. returns the size of the frame that was read or 0 if no frames are available to
be read.
*/
ssize_t AP_HAL::UARTDriver::read_frame(uint8_t *buf, uint16_t buf_size)
{
if (lock_read_key != 0) {
return 0;
}
ssize_t ret = _read_frame(buf, buf_size);
#if AP_UART_MONITOR_ENABLED
auto monitor = _monitor_read_buffer;
if (monitor != nullptr && ret > 0) {
monitor->write(buf, ret);
}
#endif
return ret;
}

int16_t AP_HAL::UARTDriver::read(void)
{
uint8_t b;
Expand All @@ -129,6 +183,14 @@ uint32_t AP_HAL::UARTDriver::available()
return _available();
}

bool AP_HAL::UARTDriver::frame_available()
{
if (lock_read_key != 0) {
return 0;
}
return _frame_available();
}

void AP_HAL::UARTDriver::end()
{
if (lock_read_key != 0 || lock_write_key != 0) {
Expand Down
45 changes: 44 additions & 1 deletion libraries/AP_HAL/UARTDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
*/
void begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace);

/*
begin in frame-based mode. the framing API works on top of the
existing UART infrastructure and framing can be started at any
time after the UART has been started. Consumed frames can be at most frame_size
bytes long, frames longer than this will be considered corrupt and the
framing buffer will be reset. The framing buffer holds at most
frames_in_buffer frames, the frames are stored in a ring buffer and so
older frames that have not been read will be overwritten.
Returns true if the framing API could be started, false otherwise
*/
bool begin_framing(uint16_t max_frame_size);

/*
begin for use when the port is write locked. Note that this does
not lock the port, an existing write_key from lock_port() must
Expand All @@ -54,8 +66,17 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
int16_t read(void) override;
bool read(uint8_t &b) override WARN_IF_UNUSED;
ssize_t read(uint8_t *buffer, uint16_t count) override;


/*
frame-based read. An entire frame will be read into buffer. count indicates the size of the
buffer and if this is less than the size of the frame to be read, the remaining bytes in the frame will
be discarded. returns the size of the frame that was read or 0 if no frames are available to
be read.
*/
ssize_t read_frame(uint8_t *buffer, uint16_t count);

void end();
void end_framing();
void flush();

virtual bool is_initialized() = 0;
Expand All @@ -67,6 +88,7 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
// check data available for read, return 0 is not available
uint32_t available() override;
uint32_t available_locked(uint32_t key);
bool frame_available();

// discard any pending input
bool discard_input() override;
Expand Down Expand Up @@ -189,12 +211,22 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
// key for a locked port
uint32_t lock_write_key;
uint32_t lock_read_key;
uint16_t frame_size = 1;

/*
backend begin method
*/
virtual void _begin(uint32_t baud, uint16_t rxSpace, uint16_t txSpace) = 0;

/*
backend begin in frame-based mode. see the documentation for begin_framing()
*/
virtual bool _begin_framing(uint16_t max_frame_size) {
return false;
}

virtual void _end_framing() { }

/*
backend write method
*/
Expand All @@ -205,6 +237,14 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
*/
virtual ssize_t _read(uint8_t *buffer, uint16_t count) WARN_IF_UNUSED = 0;

/*
frame-based read. see the documentation for read_frame()
*/
virtual ssize_t _read_frame(uint8_t *buffer, uint16_t buf_size) {
// a simplistic implementation that simply reads bytes using _read()
return _read(buffer, buf_size < frame_size ? buf_size : frame_size);
}

/*
end control of the port, freeing buffers
*/
Expand All @@ -218,6 +258,9 @@ class AP_HAL::UARTDriver : public AP_HAL::BetterStream {
// check available data on the port
virtual uint32_t _available() = 0;

// check for available frames
virtual bool _frame_available() { return available() != 0; }

// discard incoming data on the port
virtual bool _discard_input(void) = 0;

Expand Down
Loading
Loading