libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::LinuxUART Class Reference
Inheritance diagram for LibXR::LinuxUART:
[legend]
Collaboration diagram for LibXR::LinuxUART:
[legend]

Public Member Functions

 LinuxUART (const char *dev_path, unsigned int baudrate=115200, Parity parity=Parity::NO_PARITY, uint8_t data_bits=8, uint8_t stop_bits=1, uint32_t tx_queue_size=5, size_t buffer_size=512)
 
 LinuxUART (const std::string &vid, const std::string &pid, unsigned int baudrate=115200, Parity parity=Parity::NO_PARITY, uint8_t data_bits=8, uint8_t stop_bits=1, uint32_t tx_queue_size=5, size_t buffer_size=512)
 
std::string GetByPathForTTY (const std::string &tty_name)
 
void SetLowLatency (int fd)
 
ErrorCode SetConfig (UART::Configuration config) override
 设置 UART 配置 / Sets the UART configuration
 
- Public Member Functions inherited from LibXR::UART
template<typename ReadPortType = ReadPort, typename WritePortType = WritePort>
 UART (ReadPortType *read_port, WritePortType *write_port)
 UART 构造函数 / UART constructor.
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< WriteOperation, std::decay_t<OperationType>>>>
ErrorCode Write (ConstRawData data, OperationType &&op)
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< ReadOperation, std::decay_t<OperationType>>>>
ErrorCode Read (RawData data, OperationType &&op)
 

Static Public Member Functions

static bool FindUSBTTYByVidPid (const std::string &target_vid, const std::string &target_pid, std::string &tty_path)
 
static ErrorCode ReadFun (ReadPort &port)
 
static ErrorCode WriteFun (WritePort &port)
 

Private Member Functions

void RxLoop ()
 
void TxLoop ()
 

Private Attributes

int fd_ = -1
 
bool connected_ = true
 
Configuration config_
 
std::string device_path_
 
Thread rx_thread_
 
Thread tx_thread_
 
uint8_t * rx_buff_ = nullptr
 
uint8_t * tx_buff_ = nullptr
 
size_t buff_size_ = 0
 
Semaphore write_sem_
 
Mutex read_mutex_
 
ReadPort _read_port
 
WritePort _write_port
 

Additional Inherited Members

- Public Types inherited from LibXR::UART
enum class  Parity : uint8_t { NO_PARITY = 0 , EVEN = 1 , ODD = 2 }
 奇偶校验模式 / Parity mode More...
 
- Data Fields inherited from LibXR::UART
ReadPortread_port_
 读取端口 / Read port
 
WritePortwrite_port_
 写入端口 / Write port
 

Detailed Description

Definition at line 26 of file linux_uart.hpp.

Constructor & Destructor Documentation

◆ LinuxUART() [1/2]

LibXR::LinuxUART::LinuxUART ( const char * dev_path,
unsigned int baudrate = 115200,
Parity parity = Parity::NO_PARITY,
uint8_t data_bits = 8,
uint8_t stop_bits = 1,
uint32_t tx_queue_size = 5,
size_t buffer_size = 512 )
inline

Definition at line 29 of file linux_uart.hpp.

32 : UART(&_read_port, &_write_port),
33 rx_buff_(new uint8_t[buffer_size]),
34 tx_buff_(new uint8_t[buffer_size]),
35 buff_size_(buffer_size),
36 _read_port(buffer_size),
37 _write_port(tx_queue_size, buffer_size)
38 {
39 ASSERT(buff_size_ > 0);
40
41 if (std::filesystem::exists(dev_path) == false)
42 {
43 XR_LOG_ERROR("Cannot find UART device: %s", dev_path);
44 ASSERT(false);
45 }
46
47 device_path_ = GetByPathForTTY(dev_path);
48
49 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
50 if (fd_ < 0)
51 {
52 XR_LOG_ERROR("Cannot open UART device: %s", device_path_.c_str());
53 ASSERT(false);
54 }
55 else
56 {
57 XR_LOG_PASS("Open UART device: %s", device_path_.c_str());
58 }
59
60 config_ = {.baudrate = baudrate,
61 .parity = parity,
62 .data_bits = data_bits,
63 .stop_bits = stop_bits};
64
65 SetConfig(config_);
66
67 _read_port = ReadFun;
68 _write_port = WriteFun;
69
70 rx_thread_.Create<LinuxUART *>(
71 this, [](LinuxUART *self) { self->RxLoop(); }, "rx_uart", 8192,
73
74 tx_thread_.Create<LinuxUART *>(
75 this, [](LinuxUART *self) { self->TxLoop(); }, "tx_uart", 8192,
77 }
ErrorCode SetConfig(UART::Configuration config) override
设置 UART 配置 / Sets the UART configuration
@ REALTIME
实时优先级 Realtime priority
void Create(ArgType arg, void(*function)(ArgType arg), const char *name, size_t stack_depth, Thread::Priority priority)
创建新线程 Creates a new thread
Definition thread.hpp:64
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
Definition uart.hpp:66
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:246
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:242

◆ LinuxUART() [2/2]

LibXR::LinuxUART::LinuxUART ( const std::string & vid,
const std::string & pid,
unsigned int baudrate = 115200,
Parity parity = Parity::NO_PARITY,
uint8_t data_bits = 8,
uint8_t stop_bits = 1,
uint32_t tx_queue_size = 5,
size_t buffer_size = 512 )
inline

Definition at line 79 of file linux_uart.hpp.

83 : UART(&_read_port, &_write_port),
84 rx_buff_(new uint8_t[buffer_size]),
85 tx_buff_(new uint8_t[buffer_size]),
86 buff_size_(buffer_size),
87 _read_port(buffer_size),
88 _write_port(tx_queue_size, buffer_size)
89 {
90 while (!FindUSBTTYByVidPid(vid, pid, device_path_))
91 {
92 XR_LOG_WARN("Cannot find USB TTY device with VID=%s PID=%s, retrying...",
93 vid.c_str(), pid.c_str());
94 Thread::Sleep(100);
95 }
96
97 XR_LOG_PASS("Found USB TTY: %s", device_path_.c_str());
98
99 if (std::filesystem::exists(device_path_) == false)
100 {
101 XR_LOG_ERROR("Cannot find UART device: %s", device_path_.c_str());
102 ASSERT(false);
103 return;
104 }
105
106 device_path_ = GetByPathForTTY(device_path_);
107
108 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
109 if (fd_ < 0)
110 {
111 XR_LOG_ERROR("Cannot open UART device: %s", device_path_.c_str());
112 ASSERT(false);
113 }
114 else
115 {
116 XR_LOG_PASS("Open UART device: %s", device_path_.c_str());
117 }
118
119 config_ = {.baudrate = baudrate,
120 .parity = parity,
121 .data_bits = data_bits,
122 .stop_bits = stop_bits};
123
124 SetConfig(config_);
125
126 _read_port = ReadFun;
127 _write_port = WriteFun;
128
129 rx_thread_.Create<LinuxUART *>(
130 this, [](LinuxUART *self) { self->RxLoop(); }, "rx_uart", 8192,
132
133 tx_thread_.Create<LinuxUART *>(
134 this, [](LinuxUART *self) { self->TxLoop(); }, "tx_uart", 8192,
136 }
static void Sleep(uint32_t milliseconds)
让线程进入休眠状态 Puts the thread to sleep
Definition thread.cpp:16

Member Function Documentation

◆ FindUSBTTYByVidPid()

static bool LibXR::LinuxUART::FindUSBTTYByVidPid ( const std::string & target_vid,
const std::string & target_pid,
std::string & tty_path )
inlinestatic

Definition at line 157 of file linux_uart.hpp.

159 {
160 struct udev *udev = udev_new();
161 if (!udev)
162 {
163 XR_LOG_ERROR("Cannot create udev context");
164 return false;
165 }
166
167 struct udev_enumerate *enumerate = udev_enumerate_new(udev);
168 udev_enumerate_add_match_subsystem(enumerate, "tty");
169 udev_enumerate_scan_devices(enumerate);
170
171 struct udev_list_entry *devices = udev_enumerate_get_list_entry(enumerate);
172 struct udev_list_entry *entry;
173 bool found = false;
174
175 udev_list_entry_foreach(entry, devices)
176 {
177 const char *path = udev_list_entry_get_name(entry);
178 struct udev_device *tty_dev = udev_device_new_from_syspath(udev, path);
179 if (!tty_dev) continue;
180
181 struct udev_device *usb_dev =
182 udev_device_get_parent_with_subsystem_devtype(tty_dev, "usb", "usb_device");
183
184 if (usb_dev)
185 {
186 const char *vid = udev_device_get_sysattr_value(usb_dev, "idVendor");
187 const char *pid = udev_device_get_sysattr_value(usb_dev, "idProduct");
188
189 if (vid && pid && target_vid == vid && target_pid == pid)
190 {
191 const char *devnode = udev_device_get_devnode(tty_dev);
192 if (devnode)
193 {
194 tty_path = devnode;
195 found = true;
196 udev_device_unref(tty_dev);
197 break;
198 }
199 }
200 }
201
202 udev_device_unref(tty_dev);
203 }
204
205 udev_enumerate_unref(enumerate);
206 udev_unref(udev);
207 return found;
208 }

◆ GetByPathForTTY()

std::string LibXR::LinuxUART::GetByPathForTTY ( const std::string & tty_name)
inline

Definition at line 138 of file linux_uart.hpp.

139 {
140 const std::string BASE = "/dev/serial/by-path";
141 if (strncmp(tty_name.c_str(), BASE.c_str(), BASE.length()) == 0 ||
142 !std::filesystem::exists(BASE))
143 {
144 return tty_name;
145 }
146 for (const auto &entry : std::filesystem::directory_iterator(BASE))
147 {
148 std::string full = std::filesystem::canonical(entry.path());
149 if (full == tty_name)
150 {
151 return entry.path(); // 返回符号链接路径
152 }
153 }
154 return ""; // 没找到
155 }

◆ ReadFun()

static ErrorCode LibXR::LinuxUART::ReadFun ( ReadPort & port)
inlinestatic

Definition at line 331 of file linux_uart.hpp.

331{ return ErrorCode::EMPTY; }

◆ RxLoop()

void LibXR::LinuxUART::RxLoop ( )
inlineprivate

Definition at line 341 of file linux_uart.hpp.

342 {
343 while (true)
344 {
345 if (!connected_)
346 {
347 close(fd_);
348 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
349
350 if (fd_ < 0)
351 {
352 XR_LOG_WARN("Cannot open UART device: %s", device_path_.c_str());
353 Thread::Sleep(1000);
354 }
355 else
356 {
357 SetConfig(config_);
358 XR_LOG_PASS("Reopen UART device: %s", device_path_.c_str());
359 connected_ = true;
360 }
361 }
362 auto n = read(fd_, rx_buff_, buff_size_);
363 if (n > 0)
364 {
365 read_port_->queue_data_->PushBatch(rx_buff_, n);
367 }
368 else
369 {
370 XR_LOG_WARN("Cannot read UART device: %s", device_path_.c_str());
371 connected_ = false;
372 }
373 }
374 }
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue
virtual void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:126
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:53

◆ SetConfig()

ErrorCode LibXR::LinuxUART::SetConfig ( UART::Configuration config)
inlineoverridevirtual

设置 UART 配置 / Sets the UART configuration

Parameters
configUART 配置信息 / UART configuration settings
Returns
返回操作状态,成功时返回 ErrorCode::OK,否则返回相应错误码 / Returns the operation status, ErrorCode::OK if successful, otherwise an error code

该方法为纯虚函数,子类必须实现具体的 UART 配置逻辑。 This is a pure virtual function. Subclasses must implement the specific UART configuration logic.

Implements LibXR::UART.

Definition at line 218 of file linux_uart.hpp.

219 {
220 if (&config != &config_)
221 {
222 config_ = config;
223 }
224
225 struct termios2 tio
226 {
227 };
228 if (ioctl(fd_, TCGETS2, &tio) != 0)
229 {
230 return ErrorCode::INIT_ERR;
231 }
232
233 // 设置自定义波特率
234 tio.c_cflag &= ~CBAUD;
235 tio.c_cflag |= BOTHER;
236 tio.c_ispeed = config.baudrate;
237 tio.c_ospeed = config.baudrate;
238
239 // 输入模式:关闭软件流控、特殊字符处理
240 tio.c_iflag &= ~(IXON | IXOFF | IXANY | ISTRIP | IGNCR | INLCR | ICRNL
241#ifdef IUCLC
242 | IUCLC
243#endif
244 );
245
246 // 输出模式:关闭所有加工
247 tio.c_oflag &= ~(OPOST
248#ifdef ONLCR
249 | ONLCR
250#endif
251#ifdef OCRNL
252 | OCRNL
253#endif
254#ifdef ONOCR
255 | ONOCR
256#endif
257#ifdef ONLRET
258 | ONLRET
259#endif
260 );
261
262 // 本地模式:禁用行缓冲、回显、信号中断
263 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
264
265 // 控制模式:设置数据位、校验、停止位、流控
266 tio.c_cflag &= ~CSIZE;
267 switch (config.data_bits)
268 {
269 case 5:
270 tio.c_cflag |= CS5;
271 break;
272 case 6:
273 tio.c_cflag |= CS6;
274 break;
275 case 7:
276 tio.c_cflag |= CS7;
277 break;
278 case 8:
279 tio.c_cflag |= CS8;
280 break;
281 default:
282 return ErrorCode::ARG_ERR;
283 }
284
285 // 停止位
286 tio.c_cflag &= ~CSTOPB;
287 if (config.stop_bits == 2)
288 {
289 tio.c_cflag |= CSTOPB;
290 }
291
292 // 奇偶校验
293 switch (config.parity)
294 {
296 tio.c_cflag &= ~PARENB;
297 break;
299 tio.c_cflag |= PARENB;
300 tio.c_cflag &= ~PARODD;
301 break;
303 tio.c_cflag |= PARENB;
304 tio.c_cflag |= PARODD;
305 break;
306 }
307
308 // 禁用硬件流控
309 tio.c_cflag &= ~CRTSCTS;
310
311 // 启用本地模式、读功能
312 tio.c_cflag |= (CLOCAL | CREAD);
313
314 // 控制字符配置:阻塞直到读到 1 字节
315 // for (int i = 0; i < NCCS; ++i) tio.c_cc[i] = 0;
316 tio.c_cc[VTIME] = 0;
317 tio.c_cc[VMIN] = 1;
318
319 if (ioctl(fd_, TCSETS2, &tio) != 0)
320 {
321 return ErrorCode::INIT_ERR;
322 }
323
324 SetLowLatency(fd_);
325
326 tcflush(fd_, TCIOFLUSH);
327
328 return ErrorCode::OK;
329 }
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity

◆ SetLowLatency()

void LibXR::LinuxUART::SetLowLatency ( int fd)
inline

Definition at line 210 of file linux_uart.hpp.

211 {
212 struct serial_struct serinfo;
213 ioctl(fd, TIOCGSERIAL, &serinfo);
214 serinfo.flags |= ASYNC_LOW_LATENCY;
215 ioctl(fd, TIOCSSERIAL, &serinfo);
216 }

◆ TxLoop()

void LibXR::LinuxUART::TxLoop ( )
inlineprivate

Definition at line 376 of file linux_uart.hpp.

377 {
378 WriteInfoBlock info;
379 while (true)
380 {
381 if (!connected_)
382 {
383 Thread::Sleep(1);
384 continue;
385 }
386
387 if (write_sem_.Wait() != ErrorCode::OK)
388 {
389 continue;
390 }
391
392 if (write_port_->queue_info_->Pop(info) == ErrorCode::OK)
393 {
394 if (write_port_->queue_data_->PopBatch(tx_buff_, info.data.size_) ==
395 ErrorCode::OK)
396 {
397 auto written = write(fd_, tx_buff_, info.data.size_);
398 if (written < 0)
399 {
400 XR_LOG_WARN("Cannot write UART device: %s", device_path_.c_str());
401 connected_ = false;
402 }
403 write_port_->Finish(false,
404 (written == static_cast<int>(info.data.size_))
405 ? ErrorCode::OK
406 : ErrorCode::FAILED,
407 info, written);
408 }
409 else
410 {
411 info.op.UpdateStatus(false, ErrorCode::FAILED);
412 }
413 }
414 }
415 }
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:207

◆ WriteFun()

static ErrorCode LibXR::LinuxUART::WriteFun ( WritePort & port)
inlinestatic

Definition at line 333 of file linux_uart.hpp.

334 {
335 auto uart = CONTAINER_OF(&port, LinuxUART, _write_port);
336 uart->write_sem_.Post();
337 return ErrorCode::OK;
338 }

Field Documentation

◆ _read_port

ReadPort LibXR::LinuxUART::_read_port
private

Definition at line 429 of file linux_uart.hpp.

◆ _write_port

WritePort LibXR::LinuxUART::_write_port
private

Definition at line 430 of file linux_uart.hpp.

◆ buff_size_

size_t LibXR::LinuxUART::buff_size_ = 0
private

Definition at line 425 of file linux_uart.hpp.

◆ config_

Configuration LibXR::LinuxUART::config_
private

Definition at line 419 of file linux_uart.hpp.

◆ connected_

bool LibXR::LinuxUART::connected_ = true
private

Definition at line 418 of file linux_uart.hpp.

◆ device_path_

std::string LibXR::LinuxUART::device_path_
private

Definition at line 420 of file linux_uart.hpp.

◆ fd_

int LibXR::LinuxUART::fd_ = -1
private

Definition at line 417 of file linux_uart.hpp.

◆ read_mutex_

Mutex LibXR::LinuxUART::read_mutex_
private

Definition at line 427 of file linux_uart.hpp.

◆ rx_buff_

uint8_t* LibXR::LinuxUART::rx_buff_ = nullptr
private

Definition at line 423 of file linux_uart.hpp.

◆ rx_thread_

Thread LibXR::LinuxUART::rx_thread_
private

Definition at line 421 of file linux_uart.hpp.

◆ tx_buff_

uint8_t* LibXR::LinuxUART::tx_buff_ = nullptr
private

Definition at line 424 of file linux_uart.hpp.

◆ tx_thread_

Thread LibXR::LinuxUART::tx_thread_
private

Definition at line 422 of file linux_uart.hpp.

◆ write_sem_

Semaphore LibXR::LinuxUART::write_sem_
private

Definition at line 426 of file linux_uart.hpp.


The documentation for this class was generated from the following file: