28 LinuxUART(
const char *dev_path,
unsigned int baudrate = 115200,
30 uint8_t stop_bits = 1, uint32_t rx_queue_size = 5, uint32_t tx_queue_size = 5,
31 size_t buffer_size = 512)
32 :
UART(rx_queue_size, buffer_size, tx_queue_size, buffer_size),
34 rx_buff_(
new uint8_t[buffer_size]),
35 tx_buff_(
new uint8_t[buffer_size]),
36 buff_size_(buffer_size)
38 if (std::filesystem::exists(dev_path) ==
false)
40 XR_LOG_ERROR(
"Cannot find UART device: %s", dev_path);
44 device_path_ = GetByPathForTTY(dev_path);
46 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
49 XR_LOG_ERROR(
"Cannot open UART device: %s", device_path_.c_str());
54 XR_LOG_PASS(
"Open UART device: %s", device_path_.c_str());
59 .data_bits = data_bits,
60 .stop_bits = stop_bits};
68 this, [](
LinuxUART *self) { self->RxLoop(); },
"rx_uart", 8192,
72 this, [](
LinuxUART *self) { self->TxLoop(); },
"tx_uart", 8192,
76 std::string GetByPathForTTY(
const std::string &tty_name)
78 const std::string BASE =
"/dev/serial/by-path";
79 if (strncmp(tty_name.c_str(), BASE.c_str(), BASE.length()) == 0 ||
80 !std::filesystem::exists(BASE))
84 for (
const auto &entry : std::filesystem::directory_iterator(BASE))
86 std::string full = std::filesystem::canonical(entry.path());
95 void SetLowLatency(
int fd)
97 struct serial_struct serinfo;
98 ioctl(fd, TIOCGSERIAL, &serinfo);
99 serinfo.flags |= ASYNC_LOW_LATENCY;
100 ioctl(fd, TIOCSSERIAL, &serinfo);
105 if (&config != &config_)
110 struct termios2 tio{};
111 if (ioctl(fd_, TCGETS2, &tio) != 0)
113 return ErrorCode::INIT_ERR;
117 tio.c_cflag &= ~CBAUD;
118 tio.c_cflag |= BOTHER;
123 tio.c_iflag &= ~(IXON | IXOFF | IXANY | ISTRIP | IGNCR | INLCR | ICRNL
130 tio.c_oflag &= ~(OPOST
146 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
149 tio.c_cflag &= ~CSIZE;
165 return ErrorCode::ARG_ERR;
169 tio.c_cflag &= ~CSTOPB;
172 tio.c_cflag |= CSTOPB;
179 tio.c_cflag &= ~PARENB;
182 tio.c_cflag |= PARENB;
183 tio.c_cflag &= ~PARODD;
186 tio.c_cflag |= PARENB;
187 tio.c_cflag |= PARODD;
192 tio.c_cflag &= ~CRTSCTS;
195 tio.c_cflag |= (CLOCAL | CREAD);
202 if (ioctl(fd_, TCSETS2, &tio) != 0)
204 return ErrorCode::INIT_ERR;
209 tcflush(fd_, TCIOFLUSH);
211 return ErrorCode::OK;
219 return ErrorCode::OK;
222 static ErrorCode
WriteFun(WritePort &port)
224 auto uart = CONTAINER_OF(&port, LinuxUART,
write_port_);
225 WritePort::WriteInfo info;
226 if (port.queue_info_->Peek(info) != ErrorCode::OK)
228 return ErrorCode::EMPTY;
230 port.UpdateStatus(info.op);
231 uart->write_sem_.Post();
232 return ErrorCode::OK;
243 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
247 XR_LOG_WARN(
"Cannot open UART device: %s", device_path_.c_str());
253 XR_LOG_PASS(
"Reopen UART device: %s", device_path_.c_str());
257 auto n = read(fd_, rx_buff_, buff_size_);
261 Mutex::LockGuard guard(read_mutex_);
266 XR_LOG_WARN(
"Cannot read UART device: %s", device_path_.c_str());
274 WritePort::WriteInfo info;
284 if (
write_port_.queue_info_->Pop(info) == ErrorCode::OK)
288 auto written = write(fd_, tx_buff_, info.size);
291 XR_LOG_WARN(
"Cannot write UART device: %s", device_path_.c_str());
294 info.op.UpdateStatus(
false, (written ==
static_cast<int>(info.size))
296 : ErrorCode::FAILED);
301 info.op.UpdateStatus(
false, ErrorCode::FAILED);
308 bool connected_ =
true;
309 Configuration config_;
310 std::string device_path_;
313 uint8_t *rx_buff_ =
nullptr;
314 uint8_t *tx_buff_ =
nullptr;
315 size_t buff_size_ = 0;
316 Semaphore write_sem_;
void Create(ArgType arg, void(*function)(ArgType arg), const char *name, size_t stack_depth, Thread::Priority priority)
创建新线程 Creates a new thread