Skip to content

Commit

Permalink
uart support set_received_callback function
Browse files Browse the repository at this point in the history
  • Loading branch information
Neutree committed Aug 1, 2024
1 parent 8c07d8e commit e35b087
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 8 deletions.
14 changes: 14 additions & 0 deletions components/peripheral/include/maix_uart.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#include "stdint.h"
#include "maix_comm_base.hpp"
#include "maix_type.hpp"
#include "maix_thread.hpp"
#include <functional>

/**
* @brief maix uart peripheral driver
Expand Down Expand Up @@ -150,6 +152,13 @@ namespace maix::peripheral::uart
*/
err::Err close();

/**
* Set received callback function
* @param callback function to call when received data
* @maixpy maix.peripheral.uart.UART.set_received_callback
*/
void set_received_callback(std::function<void(uart::UART&, Bytes&)> callback);

/**
* Send data to device
* @param buff data buffer
Expand Down Expand Up @@ -233,6 +242,7 @@ namespace maix::peripheral::uart
* >0 means block until read len data or timeout.
* @return received data, bytes type.
* Attention, you need to delete the returned object yourself in C++.
* @throw Read failed will raise err.Exception error.
* @maixpy maix.peripheral.uart.UART.read
*/
Bytes *read(int len = -1, int timeout = 0);
Expand All @@ -256,6 +266,10 @@ namespace maix::peripheral::uart
uart::STOP _stopbits;
uart::FLOW_CTRL _flow_ctrl;
int _one_byte_time_us;
std::function<void(uart::UART&, Bytes&)> callback;
thread::Thread *_read_thread;
bool _read_thread_need_exit;
bool _read_thread_exit;
};

}; // namespace maix.peripheral.uart
78 changes: 74 additions & 4 deletions components/peripheral/port/linux/maix_uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "maix_log.hpp"
#include "maix_time.hpp"
#include "maix_fs.hpp"
#include "maix_thread.hpp"
#include "maix_app.hpp"
#include <linux/types.h>
#include <linux/stat.h>
#include <termios.h>
Expand Down Expand Up @@ -206,7 +208,18 @@ namespace maix::peripheral::uart

static int _uart_write(int fd, const void *buff, int len)
{
return write(fd, buff, len);
ssize_t bytes_written = write(fd, buff, len);
if (bytes_written < 0) {
log::error("uart write failed: %d", bytes_written);
return bytes_written;
}

// wait for data transmit completion
// if (tcdrain(fd) != 0) {
// log::error("uart wait write failed: %d", bytes_written);
// return -1;
// }
return bytes_written;
}

UART::UART(const std::string &port, int baudrate, uart::BITS databits,
Expand All @@ -220,6 +233,7 @@ namespace maix::peripheral::uart
_parity = parity;
_stopbits = stopbits;
_flow_ctrl = flow_ctrl;
_read_thread = nullptr;
if (!port.empty())
{
err::Err e = this->open();
Expand Down Expand Up @@ -267,14 +281,67 @@ namespace maix::peripheral::uart
{
if (_fd <= 0)
return err::ERR_NONE;
if (0 < _uart_deinit(_fd))
int ret = _uart_deinit(_fd);
_fd = -1;
if(_read_thread)
{
_read_thread_need_exit = true;
uint64_t t = time::ticks_ms();
while(!_read_thread_exit)
{
time::sleep_ms(10);
if(time::ticks_ms() - t > 5000)
{
log::error("waiting uart read thread exit");
t = time::ticks_ms();
}
}
delete _read_thread;
_read_thread = nullptr;
}
if (ret != 0)
{
log::error("uart close failed\r\n");
return err::ERR_IO;
}
return err::ERR_NONE;
}

void UART::set_received_callback(std::function<void(uart::UART&, Bytes&)> callback)
{
if(!_read_thread)
{
_read_thread_need_exit = false;
_read_thread_exit = false;
_read_thread = new thread::Thread([callback](void *args){
UART *uart = (UART*)args;
while(!app::need_exit() && !uart->_read_thread_need_exit)
{
Bytes *data = NULL;
try
{
data = uart->read(-1, -1);
}
catch(err::Exception)
{
log::error("read file failed");
break;
}
if(!data)
{
log::error("uart read data is null");
break;
}
callback(*uart, *data);
delete data;
}
uart->_read_thread_exit = true;
}, this);
_read_thread->detach();
}
this->callback = callback;
}

int UART::write(const uint8_t *buff, int len)
{
if (!is_open())
Expand Down Expand Up @@ -413,7 +480,7 @@ namespace maix::peripheral::uart
{
int wait_time = _one_byte_time_us * 30; // system maybe use some time
time::sleep_us(wait_time > 50000 ? 50000: wait_time);
if (available(0) > 0)
if (available(0) > 0 || (timeout < 0 && read_len == 0))
continue;
break;
}
Expand Down Expand Up @@ -463,7 +530,10 @@ namespace maix::peripheral::uart
break;
read_len = read(data->data + received, buff_len - received, len > 0 ? len - received : len, timeout > 0 ? t2 : timeout);
if (read_len < 0)
read_len = 0;
{
delete data;
throw err::Exception(err::Err(-read_len), "read failed");
}
received += read_len;
data->data_len = received;
if(len > 0 && received == len)
Expand Down
78 changes: 74 additions & 4 deletions components/peripheral/port/maixcam/maix_uart.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "maix_log.hpp"
#include "maix_time.hpp"
#include "maix_fs.hpp"
#include "maix_thread.hpp"
#include "maix_app.hpp"
#include <linux/types.h>
#include <linux/stat.h>
#include <termios.h>
Expand Down Expand Up @@ -206,7 +208,18 @@ namespace maix::peripheral::uart

static int _uart_write(int fd, const void *buff, int len)
{
return write(fd, buff, len);
ssize_t bytes_written = write(fd, buff, len);
if (bytes_written < 0) {
log::error("uart write failed: %d", bytes_written);
return bytes_written;
}

// wait for data transmit completion
// if (tcdrain(fd) != 0) {
// log::error("uart wait write failed: %d", bytes_written);
// return -1;
// }
return bytes_written;
}

UART::UART(const std::string &port, int baudrate, uart::BITS databits,
Expand All @@ -220,6 +233,7 @@ namespace maix::peripheral::uart
_parity = parity;
_stopbits = stopbits;
_flow_ctrl = flow_ctrl;
_read_thread = nullptr;
if (!port.empty())
{
err::Err e = this->open();
Expand Down Expand Up @@ -267,14 +281,67 @@ namespace maix::peripheral::uart
{
if (_fd <= 0)
return err::ERR_NONE;
if (0 < _uart_deinit(_fd))
int ret = _uart_deinit(_fd);
_fd = -1;
if(_read_thread)
{
_read_thread_need_exit = true;
uint64_t t = time::ticks_ms();
while(!_read_thread_exit)
{
time::sleep_ms(10);
if(time::ticks_ms() - t > 5000)
{
log::error("waiting uart read thread exit");
t = time::ticks_ms();
}
}
delete _read_thread;
_read_thread = nullptr;
}
if (ret != 0)
{
log::error("uart close failed\r\n");
return err::ERR_IO;
}
return err::ERR_NONE;
}

void UART::set_received_callback(std::function<void(uart::UART&, Bytes&)> callback)
{
if(!_read_thread)
{
_read_thread_need_exit = false;
_read_thread_exit = false;
_read_thread = new thread::Thread([callback](void *args){
UART *uart = (UART*)args;
while(!app::need_exit() && !uart->_read_thread_need_exit)
{
Bytes *data = NULL;
try
{
data = uart->read(-1, -1);
}
catch(err::Exception)
{
log::error("read file failed");
break;
}
if(!data)
{
log::error("uart read data is null");
break;
}
callback(*uart, *data);
delete data;
}
uart->_read_thread_exit = true;
}, this);
_read_thread->detach();
}
this->callback = callback;
}

int UART::write(const uint8_t *buff, int len)
{
if (!is_open())
Expand Down Expand Up @@ -413,7 +480,7 @@ namespace maix::peripheral::uart
{
int wait_time = _one_byte_time_us * 30; // system maybe use some time
time::sleep_us(wait_time > 50000 ? 50000: wait_time);
if (available(0) > 0)
if (available(0) > 0 || (timeout < 0 && read_len == 0))
continue;
break;
}
Expand Down Expand Up @@ -463,7 +530,10 @@ namespace maix::peripheral::uart
break;
read_len = read(data->data + received, buff_len - received, len > 0 ? len - received : len, timeout > 0 ? t2 : timeout);
if (read_len < 0)
read_len = 0;
{
delete data;
throw err::Exception(err::Err(-read_len), "read failed");
}
received += read_len;
data->data_len = received;
if(len > 0 && received == len)
Expand Down

0 comments on commit e35b087

Please sign in to comment.