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 write_sem_(0),
34 rx_buff_(new uint8_t[buffer_size]),
35 tx_buff_(new uint8_t[buffer_size]),
36 buff_size_(buffer_size),
37 _read_port(buffer_size),
38 _write_port(tx_queue_size, buffer_size)
39 {
40 ASSERT(buff_size_ > 0);
41
42 if (std::filesystem::exists(dev_path) == false)
43 {
44 XR_LOG_ERROR("Cannot find UART device: %s", dev_path);
45 ASSERT(false);
46 }
47
48 device_path_ = GetByPathForTTY(dev_path);
49
50 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
51 if (fd_ < 0)
52 {
53 XR_LOG_ERROR("Cannot open UART device: %s", device_path_.c_str());
54 ASSERT(false);
55 }
56 else
57 {
58 XR_LOG_PASS("Open UART device: %s", device_path_.c_str());
59 }
60
61 config_ = {.baudrate = baudrate,
62 .parity = parity,
63 .data_bits = data_bits,
64 .stop_bits = stop_bits};
65
66 SetConfig(config_);
67
68 _read_port = ReadFun;
69 _write_port = WriteFun;
70
71 rx_thread_.Create<LinuxUART *>(
72 this, [](LinuxUART *self) { self->RxLoop(); }, "rx_uart", 8192,
74
75 tx_thread_.Create<LinuxUART *>(
76 this, [](LinuxUART *self) { self->TxLoop(); }, "tx_uart", 8192,
78 }
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:64
ErrorCode(* ReadFun)(ReadPort &port)
Function pointer type for read operations.
Definition libxr_rw.hpp:247
ErrorCode(* WriteFun)(WritePort &port)
Function pointer type for write operations.
Definition libxr_rw.hpp:243

◆ 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 80 of file linux_uart.hpp.

84 : UART(&_read_port, &_write_port),
85 write_sem_(0),
86 rx_buff_(new uint8_t[buffer_size]),
87 tx_buff_(new uint8_t[buffer_size]),
88 buff_size_(buffer_size),
89 _read_port(buffer_size),
90 _write_port(tx_queue_size, buffer_size)
91 {
92 while (!FindUSBTTYByVidPid(vid, pid, device_path_))
93 {
94 XR_LOG_WARN("Cannot find USB TTY device with VID=%s PID=%s, retrying...",
95 vid.c_str(), pid.c_str());
96 Thread::Sleep(100);
97 }
98
99 XR_LOG_PASS("Found USB TTY: %s", device_path_.c_str());
100
101 if (std::filesystem::exists(device_path_) == false)
102 {
103 XR_LOG_ERROR("Cannot find UART device: %s", device_path_);
104 ASSERT(false);
105 }
106
107 device_path_ = GetByPathForTTY(device_path_);
108
109 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
110 if (fd_ < 0)
111 {
112 XR_LOG_ERROR("Cannot open UART device: %s", device_path_.c_str());
113 ASSERT(false);
114 }
115 else
116 {
117 XR_LOG_PASS("Open UART device: %s", device_path_.c_str());
118 }
119
120 config_ = {.baudrate = baudrate,
121 .parity = parity,
122 .data_bits = data_bits,
123 .stop_bits = stop_bits};
124
125 SetConfig(config_);
126
127 _read_port = ReadFun;
128 _write_port = WriteFun;
129
130 rx_thread_.Create<LinuxUART *>(
131 this, [](LinuxUART *self) { self->RxLoop(); }, "rx_uart", 8192,
133
134 tx_thread_.Create<LinuxUART *>(
135 this, [](LinuxUART *self) { self->TxLoop(); }, "tx_uart", 8192,
137 }
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 158 of file linux_uart.hpp.

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

◆ GetByPathForTTY()

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

Definition at line 139 of file linux_uart.hpp.

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

◆ ReadFun()

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

Definition at line 330 of file linux_uart.hpp.

330{ return ErrorCode::EMPTY; }

◆ RxLoop()

void LibXR::LinuxUART::RxLoop ( )
inlineprivate

Definition at line 340 of file linux_uart.hpp.

341 {
342 while (true)
343 {
344 if (!connected_)
345 {
346 close(fd_);
347 fd_ = open(device_path_.c_str(), O_RDWR | O_NOCTTY);
348
349 if (fd_ < 0)
350 {
351 XR_LOG_WARN("Cannot open UART device: %s", device_path_.c_str());
352 Thread::Sleep(1000);
353 }
354 else
355 {
356 SetConfig(config_);
357 XR_LOG_PASS("Reopen UART device: %s", device_path_.c_str());
358 connected_ = true;
359 }
360 }
361 auto n = read(fd_, rx_buff_, buff_size_);
362 if (n > 0)
363 {
364 read_port_->queue_data_->PushBatch(rx_buff_, n);
366 }
367 else
368 {
369 XR_LOG_WARN("Cannot read UART device: %s", device_path_.c_str());
370 connected_ = false;
371 }
372 }
373 }
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.hpp:501
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:51

◆ 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 219 of file linux_uart.hpp.

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

◆ SetLowLatency()

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

Definition at line 211 of file linux_uart.hpp.

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

◆ TxLoop()

void LibXR::LinuxUART::TxLoop ( )
inlineprivate

Definition at line 375 of file linux_uart.hpp.

376 {
377 WriteInfoBlock info;
378 while (true)
379 {
380 if (!connected_)
381 {
382 Thread::Sleep(1);
383 continue;
384 }
385
386 if (write_sem_.Wait() != ErrorCode::OK)
387 {
388 continue;
389 }
390
391 if (write_port_->queue_info_->Pop(info) == ErrorCode::OK)
392 {
393 if (write_port_->queue_data_->PopBatch(tx_buff_, info.data.size_) ==
394 ErrorCode::OK)
395 {
396 auto written = write(fd_, tx_buff_, info.data.size_);
397 if (written < 0)
398 {
399 XR_LOG_WARN("Cannot write UART device: %s", device_path_.c_str());
400 connected_ = false;
401 }
402 write_port_->Finish(false,
403 (written == static_cast<int>(info.data.size_))
404 ? ErrorCode::OK
405 : ErrorCode::FAILED,
406 info, written);
407 }
408 else
409 {
410 ASSERT(false);
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:52
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info, uint32_t size)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.hpp:665

◆ WriteFun()

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

Definition at line 332 of file linux_uart.hpp.

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

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: