µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
os::posix::device_serial_buffered< CS > Class Template Reference

Buffered serial driver class template.<cmsis-plus/posix-driver/circular-buffer.h> More...

#include <circular-buffer.h>

+ Inheritance diagram for os::posix::device_serial_buffered< CS >:

Public Member Functions

Constructors & Destructor
 device_serial_buffered (const char *device_name, os::driver::Serial *driver, os::posix::circular_buffer_bytes *rx_buf, os::posix::circular_buffer_bytes *tx_buf)
 
virtual ~device_serial_buffered ()
 

Static Public Member Functions

Public Static Member Functions
static void signal_event (device_serial_buffered *object, uint32_t event)
 

Protected Member Functions

Private Member Functions
virtual int do_vopen (const char *path, int oflag, std::va_list args) override
 
virtual int do_close (void) override
 
virtual ssize_t do_read (void *buf, std::size_t nbyte) override
 
virtual ssize_t do_write (const void *buf, std::size_t nbyte) override
 
virtual bool do_is_opened (void) override
 
virtual bool do_is_connected (void) override
 

Private Types

using critical_section = CS
 

Detailed Description

template<typename CS>
class os::posix::device_serial_buffered< CS >

Definition at line 52 of file device-serial-buffered.h.

Member Typedef Documentation

◆ critical_section

template<typename CS >
using os::posix::device_serial_buffered< CS >::critical_section = CS
private

Definition at line 54 of file device-serial-buffered.h.

Constructor & Destructor Documentation

◆ device_serial_buffered()

template<typename CS >
os::posix::device_serial_buffered< CS >::device_serial_buffered ( const char *  device_name,
os::driver::Serial driver,
os::posix::circular_buffer_bytes rx_buf,
os::posix::circular_buffer_bytes tx_buf 
)

Definition at line 191 of file device-serial-buffered.h.

195 : //
196 device_char (device_name), // Construct parent.
197 driver_ (driver), //
198 rx_buf_ (rx_buf), //
199 tx_buf_ (tx_buf) //
200 {
201 trace::printf ("%s(\"%s\",%p,%p,%p) %p\n", __func__, device_name, driver,
202 rx_buf, tx_buf, this);
203
204 assert (rx_buf != nullptr);
205
206 // Do not check the same for tx_buf, it may be null.
207
208 driver_->register_callback (
209 reinterpret_cast<os::driver::signal_event_t> (signal_event), this);
210 }
static void signal_event(device_serial_buffered *object, uint32_t event)
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
void(* signal_event_t)(const void *object, event_t event)
Definition common.h:67

References os::trace::printf(), and os::posix::device_serial_buffered< CS >::signal_event().

◆ ~device_serial_buffered()

template<typename CS >
os::posix::device_serial_buffered< CS >::~device_serial_buffered
virtual

Definition at line 213 of file device-serial-buffered.h.

214 {
215 trace::printf ("%s() %p\n", __func__, this);
216
217 driver_ = nullptr;
218 is_connected_ = false;
219 is_opened_ = false;
220 }

References os::trace::printf().

Member Function Documentation

◆ do_close()

template<typename CS >
int os::posix::device_serial_buffered< CS >::do_close ( void  )
overrideprotectedvirtual

Definition at line 346 of file device-serial-buffered.h.

347 {
348
349 if (is_connected_)
350 {
351 // Wait for write to complete.
352 // TODO: what if flow control prevents this?
353 if (tx_buf_ != nullptr)
354 {
355 for (;;)
356 {
357 if (tx_buf_->empty ())
358 {
359 break;
360 }
361 tx_sem_.wait ();
362 }
363 }
364 }
365
366 // Abort pending reads.
368 ret = driver_->control (os::driver::serial::Control::abort_receive);
369 assert (ret == os::driver::RETURN_OK);
370
371 // Abort pending writes.
372 ret = driver_->control (os::driver::serial::Control::abort_send);
373 assert (ret == os::driver::RETURN_OK);
374
375 // Disable transmitter and receiver.
376 ret = driver_->control (os::driver::serial::Control::disable_tx);
377 assert (ret == os::driver::RETURN_OK);
378
379 ret = driver_->control (os::driver::serial::Control::disable_rx);
380 assert (ret == os::driver::RETURN_OK);
381 ret = driver_->control (os::driver::serial::Control::disable_break);
382 assert (ret == os::driver::RETURN_OK);
383
384 is_opened_ = false;
385 is_connected_ = false;
386
387 // Return POSIX idea of OK.
388 return 0;
389 }
@ abort_receive
Abort Serial::receive().
Definition serial.h:203
@ abort_send
Abort Serial::send().
Definition serial.h:200
@ disable_break
Disable Continuous Break transmission;.
Definition serial.h:215
@ disable_tx
Disable Transmitter.
Definition serial.h:209
@ disable_rx
Disable Receiver.
Definition serial.h:212
constexpr return_t RETURN_OK
Definition common.h:52
int32_t return_t
Definition common.h:46

References os::driver::serial::abort_receive, os::driver::serial::abort_send, os::driver::serial::disable_break, os::driver::serial::disable_rx, os::driver::serial::disable_tx, and os::driver::RETURN_OK.

◆ do_is_connected()

template<typename CS >
bool os::posix::device_serial_buffered< CS >::do_is_connected ( void  )
overrideprotectedvirtual

Definition at line 339 of file device-serial-buffered.h.

340 {
341 return is_connected_;
342 }

◆ do_is_opened()

template<typename CS >
bool os::posix::device_serial_buffered< CS >::do_is_opened ( void  )
overrideprotectedvirtual

Definition at line 332 of file device-serial-buffered.h.

333 {
334 return is_opened_;
335 }

◆ do_read()

template<typename CS >
ssize_t os::posix::device_serial_buffered< CS >::do_read ( void *  buf,
std::size_t  nbyte 
)
overrideprotectedvirtual

Definition at line 393 of file device-serial-buffered.h.

394 {
395 // TODO: implement cases when 0 must be returned
396 // (disconnects, timeouts).
397 while (true)
398 {
399 std::size_t count;
400 {
401 // ----- Enter critical section -------------------------------
403
404 count = rx_buf_->pop_front (static_cast<uint8_t*> (buf), nbyte);
405 // ----- Exit critical section --------------------------------
406 }
407 if (count > 0)
408 {
409 // Actual number of chars received in buffer.
410 return count;
411 }
412 if (!is_connected_)
413 {
414 errno = EIO;
415 return -1;
416 }
417 // Block and wait for bytes to arrive.
418 rx_sem_.wait ();
419 }
420 }

◆ do_vopen()

template<typename CS >
int os::posix::device_serial_buffered< CS >::do_vopen ( const char *  path,
int  oflag,
std::va_list  args 
)
overrideprotectedvirtual

Definition at line 232 of file device-serial-buffered.h.

234 {
235 if (is_opened_)
236 {
237 errno = EEXIST; // Already opened
238 return -1;
239 }
240
241 int32_t result;
242
243 do
244 {
245 // Reset semaphores, in case we come here after close.
246 open_sem_.reset ();
247 rx_sem_.reset ();
248 tx_sem_.reset ();
249
250 is_opened_ = true;
251
252 // Clear buffers.
253 rx_buf_->clear ();
254 rx_count_ = 0;
255
256 if (tx_buf_ != nullptr)
257 {
258 tx_buf_->clear ();
259 }
260
261 // Default configuration: 8 bits, no parity, 1 stop bit,
262 // no flow control, 115200 bps.
263 result = driver_->configure (
269 115200);
270 // assert(result == os::driver::RETURN_OK);
271 if (result != os::driver::RETURN_OK)
272 break;
273
274 // Enable TX output.
275 result = driver_->control (os::driver::serial::Control::enable_tx);
276 if (result != os::driver::RETURN_OK)
277 break;
278
279 // Enable RX input.
280 result = driver_->control (os::driver::serial::Control::enable_rx);
281 if (result != os::driver::RETURN_OK)
282 break;
283 }
284 while (false); // Actually NOT a loop, just a sequence of ifs!
285
286 if (result != os::driver::RETURN_OK)
287 {
288 errno = EIO;
289 return -1;
290 }
291
293 capa = driver_->get_capabilities ();
294 if (capa.dcd)
295 {
297 for (;;)
298 {
299 {
300 // ----- Enter critical section ---------------------------
302
303 status = driver_->get_modem_status ();
304 // ----- Exit critical section ----------------------------
305 }
306 if (status.is_dcd_active ())
307 {
308 break;
309 }
310 open_sem_.wait ();
311 }
312 }
313
314 uint8_t* pbuf;
315 std::size_t nbyte = rx_buf_->back_contiguous_buffer (&pbuf);
316
317 result = driver_->receive (pbuf, nbyte);
318 if (result != os::driver::RETURN_OK)
319 {
320 errno = EIO;
321 return -1;
322 }
323
324 is_connected_ = true;
325
326 // Return POSIX idea of OK.
327 return 0;
328 }
Serial device driver capabilities.
Definition serial.h:455
bool dcd
DCD Line: false=not available, true=available.
Definition serial.h:506
Serial modem status
Definition serial.h:355
constexpr config_t PARITY_NONE
No Parity = (default);.
Definition serial.h:104
constexpr config_t DATA_BITS_8
8 Data bits = (default);.
Definition serial.h:94
constexpr config_t STOP_BITS_1
1 Stop bit = (default);.
Definition serial.h:117
constexpr config_t MODE_ASYNCHRONOUS
UART = (Asynchronous);; arg = Baudrate.
Definition serial.h:62
constexpr config_t FLOW_CONTROL_NONE
No Flow Control = (default);.
Definition serial.h:133
@ enable_tx
Enable Transmitter.
Definition serial.h:191
@ enable_rx
Enable Receiver.
Definition serial.h:194

References os::driver::serial::DATA_BITS_8, os::driver::serial::Capabilities::dcd, os::driver::serial::enable_rx, os::driver::serial::enable_tx, os::driver::serial::FLOW_CONTROL_NONE, os::driver::serial::Modem_status::is_dcd_active(), os::driver::serial::MODE_ASYNCHRONOUS, os::driver::serial::PARITY_NONE, os::driver::RETURN_OK, and os::driver::serial::STOP_BITS_1.

◆ do_write()

template<typename CS >
ssize_t os::posix::device_serial_buffered< CS >::do_write ( const void *  buf,
std::size_t  nbyte 
)
overrideprotectedvirtual

Definition at line 424 of file device-serial-buffered.h.

425 {
426 std::size_t count;
427
428 if (tx_buf_ != nullptr)
429 {
430 count = 0;
431 {
432 // ----- Enter critical section -------------------------------
434
435 if (tx_buf_->below_high_water_mark ())
436 {
437 // If there is more space in the buffer, try to fill it.
438 count = tx_buf_->push_back (static_cast<const uint8_t*> (buf),
439 nbyte);
440 }
441 // ----- Exit critical section --------------------------------
442 }
443 while (true)
444 {
446 {
447 // ----- Enter critical section ---------------------------
449
450#pragma GCC diagnostic push
451#if defined(__clang__)
452#elif defined(__GNUC__)
453#pragma GCC diagnostic ignored "-Waggregate-return"
454#endif
455 status = driver_->get_status ();
456#pragma GCC diagnostic pop
457
458 // ----- Exit critical section ----------------------------
459 }
460 if (!status.tx_busy)
461 {
462 uint8_t* pbuf;
463 std::size_t nb;
464 {
465 // ----- Enter critical section -----------------------
466 critical_section cs; // -----
467
468 nb = tx_buf_->front_contiguous_buffer (&pbuf);
469 // ----- Exit critical section ------------------------
470 }
471 if (nb > 0)
472 {
473 if (driver_->send (pbuf, nb) != os::driver::RETURN_OK)
474 {
475 errno = EIO;
476 return -1;
477 }
478 }
479 }
480
481 // bool isBelowHWM;
482 // {
483 // critical_section cs; // -----
484 //
485 // isBelowHWM = tx_buf_->below_high_water_mark
486 // ();
487 // }
488 if (count == nbyte)
489 {
490 return nbyte;
491 }
492
493 if (!is_connected_)
494 {
495 if (count > 0)
496 {
497 return count;
498 }
499
500 errno = EIO;
501 return -1;
502 }
503
504 // Block and wait for buffer to be freed.
505 tx_sem_.wait ();
506
507 if (count < nbyte)
508 {
509 // ----- Enter critical section ---------------------------
511
512 std::size_t n;
513 // If there is more space in the buffer, try to fill it.
514 n = tx_buf_->push_back (static_cast<const uint8_t*> (buf)
515 + count,
516 nbyte - count);
517 count += n;
518 // ----- Exit critical section ----------------------------
519 }
520 }
521 }
522 else
523 {
524 // Do not use a transmit buffer, send directly from the user buffer.
525 // Wait while transmitting.
527 for (;;)
528 {
529 if (!is_connected_)
530 {
531 errno = EIO;
532 return -1;
533 }
534
535 status = driver_->get_status ();
536 if (!status.is_tx_busy ())
537 {
538 break;
539 }
540 tx_sem_.wait ();
541 }
542
543 if ((driver_->send (buf, nbyte)) == os::driver::RETURN_OK)
544 {
545 for (;;)
546 {
547 if (!is_connected_)
548 {
549 errno = EIO;
550 return -1;
551 }
552
553 status = driver_->get_status ();
554 if (!status.is_tx_busy ())
555 {
556 break;
557 }
558 tx_sem_.wait ();
559 }
560 count = driver_->get_tx_count ();
561 }
562 else
563 {
564 count = -1;
565 errno = EIO;
566 }
567 }
568
569 // Actual number of bytes transmitted from buffer.
570 return count;
571 }
Serial port status
Definition serial.h:259
bool tx_busy
Transmitter busy flag.
Definition serial.h:289

References os::driver::serial::Status::is_tx_busy(), os::driver::RETURN_OK, and os::driver::serial::Status::tx_busy.

◆ signal_event()

template<typename CS >
void os::posix::device_serial_buffered< CS >::signal_event ( device_serial_buffered< CS > *  object,
uint32_t  event 
)
static

Definition at line 603 of file device-serial-buffered.h.

605 {
606 if (!object->is_opened_)
607 {
608 // After close(), ignore interrupts.
609 return;
610 }
611 if ((event
615 {
616 // TODO: process errors and timeouts
617 std::size_t tmpCount = object->driver_->get_rx_count ();
618 std::size_t count = tmpCount - object->rx_count_;
619 object->rx_count_ = tmpCount;
620 std::size_t adjust = object->rx_buf_->advance_back (count);
621 assert (count == adjust);
622
624 {
625 uint8_t* pbuf;
626 std::size_t nbyte
627 = object->rx_buf_->back_contiguous_buffer (&pbuf);
628 if (nbyte == 0)
629 {
630 // Overwrite the last byte, but keep the driver in
631 // receive mode continuously.
632 object->rx_buf_->retreat_back ();
633 nbyte = object->rx_buf_->back_contiguous_buffer (&pbuf);
634 }
635 assert (nbyte > 0);
636
637 // Read as much as we can.
638 int32_t status;
639 status = object->driver_->receive (pbuf, nbyte);
640 // TODO: implement error processing.
641 assert (status == os::driver::RETURN_OK);
642
643 object->rx_count_ = 0;
644 }
645 if (count > 0)
646 {
647 // Immediately wake up, do not wait to reach any water mark.
648 object->rx_sem_.post ();
649 }
650 }
652 {
653 if (object->tx_buf_ != nullptr)
654 {
655 std::size_t count = object->driver_->get_tx_count ();
656 std::size_t adjust = object->tx_buf_->advance_front (count);
657 assert (count == adjust);
658
659 uint8_t* pbuf;
660 std::size_t nbyte
661 = object->tx_buf_->front_contiguous_buffer (&pbuf);
662 if (nbyte > 0)
663 {
664 int32_t status;
665 status = object->driver_->send (pbuf, nbyte);
666 // TODO: implement error processing
667 assert (status == os::driver::RETURN_OK);
668 }
669 else
670 {
671 object->tx_busy_ = false;
672 }
673 if (object->tx_buf_->below_low_water_mark ())
674 {
675 // Wake up thread, to come and send more bytes.
676 object->tx_sem_.post ();
677 }
678 }
679 else
680 {
681 // No buffer, wake up the thread to return from write().
682 object->tx_sem_.post ();
683 }
684 }
686 {
688 status = object->driver_->get_modem_status ();
689
690 bool is_dcd_active = status.is_dcd_active ();
691 object->is_connected_ = is_dcd_active;
692 if (is_dcd_active)
693 {
694 // Connected, wake-up open().
695 object->open_sem_.post ();
696 }
697 else
698 {
699 // Disconnected, cancel read.
700 object->rx_sem_.post ();
701
702 // Cancel write.
703 object->tx_sem_.post ();
704 }
705 }
707 {
708 // TODO: add flow control
709 }
711 {
712 // TODO: add flow control
713 }
714 }
@ cts
CTS state changed (optional).
Definition serial.h:430
@ rx_framing_error
Framing error detected on receive.
Definition serial.h:424
@ dsr
DSR state changed (optional).
Definition serial.h:433
@ dcd
DCD state changed (optional).
Definition serial.h:436
@ rx_timeout
Receive character timeout (optional).
Definition serial.h:418
@ receive_complete
Receive completed.
Definition serial.h:403
@ tx_complete
Transmit completed (optional).
Definition serial.h:409

References os::driver::serial::cts, os::driver::serial::dcd, os::driver::serial::dsr, os::driver::serial::Modem_status::is_dcd_active(), os::driver::serial::receive_complete, os::driver::RETURN_OK, os::driver::serial::rx_framing_error, os::driver::serial::rx_timeout, and os::driver::serial::tx_complete.

Referenced by os::posix::device_serial_buffered< CS >::device_serial_buffered().


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