Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Pic32mxCdc Class Reference

Device driver for PIC32MX USB virtual serial port. More...

Inheritance diagram for Pic32mxCdc:
Serial Atomic Node Device FileIO

Public Member Functions

 Pic32mxCdc (const char *name)
 Constructor.
 
 ~Pic32mxCdc ()
 Destructor.
 
void interrupt_handler ()
 Handle an interrupt.
 
void device_tasks ()
 Background thread for doing USB device driver tasks.
 
void event_hander_from_isr (USB_DEVICE_EVENT event, void *pData)
 This function is called from the interrupt context of the USB driver to notify us about various events at the driver layer, such as USB plugged in.
 
USB_DEVICE_CDC_EVENT_RESPONSE cdc_event_hander_from_isr (USB_DEVICE_CDC_EVENT event, void *pData)
 This function is called from the interrupt context of the USB driver to notify us about various events at the CDC layer, such as TX complete.
 
- Public Member Functions inherited from Device
 Device (const char *name)
 Constructor.
 
virtual ~Device ()
 Destructor.
 

Private Member Functions

void tx_char () override
 Unused.
 
void enable () override
 Called by the serial driver when the first fd gets opened.
 
void disable () override
 Called by the serial driver when the last fd gets closed.
 
void flush_buffers () override
 Called by the serial driver after the last fd gets closed.
 
ssize_t read (File *file, void *buf, size_t count) override
 Read from a file or device.
 
ssize_t write (File *file, const void *buf, size_t count) OVERRIDE
 Write to a file or device.
 
bool select (File *file, int mode) override
 Device select method.
 
void start_read_atomic ()
 Issues a read to the USB driver stack.
 
void start_write_atomic ()
 Issues a write to the USB driver stack.
 
DeviceBuffer< uint8_t > * current_rx_buffer ()
 
DeviceBuffer< uint8_t > * next_rx_buffer ()
 
 Pic32mxCdc ()
 Default constructor.
 
 DISALLOW_COPY_AND_ASSIGN (Pic32mxCdc)
 
- Private Member Functions inherited from Atomic
void lock ()
 
void unlock ()
 

Private Attributes

SYS_MODULE_OBJ drvUSBObject
 Module pointer for USB core device.
 
SYS_MODULE_OBJ usbDevObject0
 Module pointer for USB middleware device.
 
USB_DEVICE_HANDLE deviceHandle {USB_DEVICE_HANDLE_INVALID}
 Equivalent of an fd for the USB core driver.
 
USB_CDC_LINE_CODING lineCodingData
 Holds last set line coding data that came from the host.
 
USB_DEVICE_CDC_TRANSFER_HANDLE readHandle
 Handle for the current pending read.
 
USB_DEVICE_CDC_TRANSFER_HANDLE writeHandle
 Handle for the current pending write.
 
unsigned isEnabled: 1
 True when we have open fds.
 
unsigned needAttach: 1
 true wehen we need to execute an attach command on the usb task.
 
unsigned isConfigured: 1
 true when we have a configured host.
 
unsigned currentReadBuffer: 1
 Index of the buffer for current (userspace) reads.
 
unsigned rxPending: 1
 true when we have an outstanding read request with the USB driver.
 
unsigned nextReadBufferFull: 1
 true if the opposite read buffer (the one after current) also has data.
 
unsigned txPendingBytes: 7
 Zero if no writes are pending, otherwise the number of bytes we sent with the pending write to the USB device driver.
 
unsigned driverErrors: 10
 Counts internal error conditions that should not occur but we are hoping we can recover from them.
 
unsigned irqVector: 5
 unused.
 
DeviceBuffer< uint8_t > * rxBuffers [2]
 Receive buffers.
 

Static Private Attributes

static constexpr unsigned USB_CDC_BUFFER_SIZE = 64
 
static constexpr unsigned TX_BUFFER_SIZE = 3 * USB_CDC_BUFFER_SIZE
 
static constexpr unsigned RX_DEVICEBUFFER_SIZE = 0
 

Additional Inherited Members

- Static Public Member Functions inherited from Device
static int open (struct _reent *reent, const char *path, int flags, int mode)
 Open a file or device.
 
static int close (struct _reent *reent, int fd)
 Close a file or device.
 
static int stat (struct _reent *reent, const char *path, struct stat *stat)
 Get the status information of a file or device.
 
static int select (int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, long long timeout)
 POSIX select().
 
static void select_clear ()
 Clears the current thread's select bits.
 
- Static Public Member Functions inherited from FileIO
static ssize_t read (struct _reent *reent, int fd, void *buf, size_t count)
 Read from a file or device.
 
static ssize_t write (struct _reent *reent, int fd, const void *buf, size_t count)
 Write to a file or device.
 
static _off_t lseek (struct _reent *reent, int fd, _off_t offset, int whence)
 Change the offset index of a file or device.
 
static int fstat (struct _reent *reent, int fd, struct stat *stat)
 Get the status information of a file or device.
 
static int ioctl (int fd, unsigned long int key, unsigned long data)
 Request and ioctl transaction.
 
static int fcntl (int fd, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
static bool is_device (int fd)
 Test if the file descriptor belongs to a device.
 
- Protected Member Functions inherited from Serial
 Serial (const char *name, size_t tx_buffer_size=config_serial_tx_buffer_size(), size_t rx_buffer_size=config_serial_rx_buffer_size())
 Constructor.
 
 ~Serial ()
 Destructor.
 
ssize_t read (File *file, void *buf, size_t count) OVERRIDE
 Read from a file or device.
 
ssize_t write (File *file, const void *buf, size_t count) OVERRIDE
 Write to a file or device.
 
int ioctl (File *file, unsigned long int key, unsigned long data) OVERRIDE
 Request an ioctl transaction.
 
bool select (File *file, int mode) OVERRIDE
 Device select method.
 
void flush_buffers () OVERRIDE
 Discards all pending buffers.
 
- Protected Member Functions inherited from Node
 Node (const char *name)
 Constructor.
 
virtual ~Node ()
 Destructor.
 
int open (File *, const char *, int, int) OVERRIDE
 Open method.
 
int close (File *) OVERRIDE
 Close method.
 
virtual int fstat (File *file, struct stat *stat) override
 Get the status information of a file or device.
 
- Protected Member Functions inherited from FileIO
 FileIO (const char *name)
 Constructor.
 
virtual ~FileIO ()
 Destructor.
 
virtual off_t lseek (File *f, off_t offset, int whence)
 Seek method.
 
virtual int fcntl (File *file, int cmd, unsigned long data)
 Manipulate a file descriptor.
 
- Static Protected Member Functions inherited from Device
static void select_insert (SelectInfo *info)
 Add client to list of clients needing woken.
 
static void select_wakeup (SelectInfo *info)
 Wakeup the list of clients needing woken.
 
static void select_wakeup_from_isr (SelectInfo *info, int *woken)
 Wakeup the list of clients needing woken.
 
- Static Protected Member Functions inherited from FileIO
static int fd_alloc (void)
 Allocate a free file descriptor.
 
static void fd_free (int fd)
 Free up a file descriptor.
 
static Filefile_lookup (int fd)
 Looks up a reference to a File corresponding to a given file descriptor.
 
static int fd_lookup (File *file)
 Looks up a file descriptor corresponding to a given File reference.
 
- Protected Attributes inherited from Serial
DeviceBuffer< uint8_t > * txBuf
 transmit buffer
 
DeviceBuffer< uint8_t > * rxBuf
 receive buffer
 
unsigned int overrunCount
 overrun count
 
- Protected Attributes inherited from Node
OSMutex lock_
 protects internal structures.
 
mode_t mode_
 File open mode, such as O_NONBLOCK.
 
unsigned int references_
 number of open references
 
- Protected Attributes inherited from FileIO
const char * name
 device name
 
- Static Protected Attributes inherited from FileIO
static const unsigned int numOpenFiles = 20
 
static File files []
 File descriptor pool.
 
static OSMutex mutex
 mutual exclusion for fileio
 

Detailed Description

Device driver for PIC32MX USB virtual serial port.

High-level decisions:

The serial port driver is compiled without RTOS support. This means all the mutexes it has internally are just bits. This can cause error values returned if we have multiple calls from different thread + interrupt context.

Major decision: whether we are calling CDC send/receive functions from the interrupt handler or not. If we don't, then we need to ensure that a user thread gets woken up when a transmit is complete and there are pending bytes in the transmit buffer. That's somewhat difficult. It's easier to call the next transmit inline in the interrupt handler, and also gives better performance (fewer context switches, less CPU usage, more throughput).

In order to achieve this, we need to ensure that all calls to the USB stack are protected by critical sections that prevent the interrupt from occuring.

A specialty of this USB driver is that write and read commands have zero-copy API, which means that the buffer pointer we give to the stack needs to remain available so long as the transfer is outstanding. We cannot use the userspace buffer pointers and have O_NONBLOCK file descriptors. So we are making one copy from user buffer into the device buffer, then give that pointer to the USB stack.

For transmit buffer we are using the standard txBuf coming from Serial. We set this transmit buffer to 3 urb length. This allows us to keep sending 64-byte packets when the application stack keeps pushing bytes at the full available throughput. For receive buffer there is a driver restriction to always give a 64-byte buffer for read. We cannot do that with a single DeviceBuffer (even if we set it to 128 byte long), thus we manage our own receive buffers. We still use DeviceBuffer class, but two of them with double buffering, as this combination allows us tracking the holes between the two buffers when a short read comes in.

Definition at line 92 of file Pic32mxUsbCdcDevice.cxx.

Constructor & Destructor Documentation

◆ Pic32mxCdc()

Pic32mxCdc::Pic32mxCdc ( const char *  name)

Constructor.

Parameters
namename of this device instance in the file system

Definition at line 267 of file Pic32mxUsbCdcDevice.cxx.

◆ ~Pic32mxCdc()

Pic32mxCdc::~Pic32mxCdc ( )

Destructor.

Definition at line 310 of file Pic32mxUsbCdcDevice.cxx.

Member Function Documentation

◆ cdc_event_hander_from_isr()

USB_DEVICE_CDC_EVENT_RESPONSE Pic32mxCdc::cdc_event_hander_from_isr ( USB_DEVICE_CDC_EVENT  event,
void *  pData 
)
inline

This function is called from the interrupt context of the USB driver to notify us about various events at the CDC layer, such as TX complete.

Definition at line 637 of file Pic32mxUsbCdcDevice.cxx.

◆ current_rx_buffer()

DeviceBuffer< uint8_t > * Pic32mxCdc::current_rx_buffer ( )
inlineprivate
Returns
the side of the double buffer from which the userspace should be reading.

Definition at line 177 of file Pic32mxUsbCdcDevice.cxx.

◆ device_tasks()

void Pic32mxCdc::device_tasks ( )
inline

Background thread for doing USB device driver tasks.

Must be called a ~dozen times per second in order to initialize, register with the USB hosts, etc.

Definition at line 559 of file Pic32mxUsbCdcDevice.cxx.

◆ disable()

void Pic32mxCdc::disable ( )
overrideprivatevirtual

Called by the serial driver when the last fd gets closed.

Implements Node.

Definition at line 337 of file Pic32mxUsbCdcDevice.cxx.

◆ enable()

void Pic32mxCdc::enable ( )
overrideprivatevirtual

Called by the serial driver when the first fd gets opened.

Implements Node.

Definition at line 316 of file Pic32mxUsbCdcDevice.cxx.

◆ event_hander_from_isr()

void Pic32mxCdc::event_hander_from_isr ( USB_DEVICE_EVENT  event,
void *  pData 
)
inline

This function is called from the interrupt context of the USB driver to notify us about various events at the driver layer, such as USB plugged in.

Definition at line 594 of file Pic32mxUsbCdcDevice.cxx.

◆ flush_buffers()

void Pic32mxCdc::flush_buffers ( )
overrideprivatevirtual

Called by the serial driver after the last fd gets closed.

Implements Node.

Definition at line 343 of file Pic32mxUsbCdcDevice.cxx.

◆ interrupt_handler()

void Pic32mxCdc::interrupt_handler ( )
inline

Handle an interrupt.

Definition at line 104 of file Pic32mxUsbCdcDevice.cxx.

◆ next_rx_buffer()

DeviceBuffer< uint8_t > * Pic32mxCdc::next_rx_buffer ( )
inlineprivate
Returns
the side of the double buffer into which the driver should be writing.

Definition at line 184 of file Pic32mxUsbCdcDevice.cxx.

◆ read()

ssize_t Pic32mxCdc::read ( File file,
void *  buf,
size_t  count 
)
overrideprivatevirtual

Read from a file or device.

Parameters
filefile reference for this device
buflocation to place read data
countnumber of bytes to read
Returns
number of bytes read upon success, -1 upon failure with errno containing the cause

Implements FileIO.

Definition at line 378 of file Pic32mxUsbCdcDevice.cxx.

◆ select()

bool Pic32mxCdc::select ( File file,
int  mode 
)
overrideprivatevirtual

Device select method.

Default impementation returns true.

Parameters
filereference to the file
modeFREAD for read active, FWRITE for write active, 0 for exceptions
Returns
true if active, false if inactive

Reimplemented from FileIO.

Definition at line 510 of file Pic32mxUsbCdcDevice.cxx.

◆ start_read_atomic()

void Pic32mxCdc::start_read_atomic ( )
private

Issues a read to the USB driver stack.

Must be called from within a lock or critical section. Uses next_rx_buffer().

Definition at line 358 of file Pic32mxUsbCdcDevice.cxx.

◆ start_write_atomic()

void Pic32mxCdc::start_write_atomic ( )
private

Issues a write to the USB driver stack.

Must be called from within a lock or critical section or interrupt.

Definition at line 429 of file Pic32mxUsbCdcDevice.cxx.

◆ tx_char()

void Pic32mxCdc::tx_char ( )
inlineoverrideprivatevirtual

Unused.

Implements Serial.

Definition at line 131 of file Pic32mxUsbCdcDevice.cxx.

◆ write()

ssize_t Pic32mxCdc::write ( File file,
const void *  buf,
size_t  count 
)
privatevirtual

Write to a file or device.

Parameters
filefile reference for this device
buflocation to find write data
countnumber of bytes to write
Returns
number of bytes written upon success, -1 upon failure with errno containing the cause

Implements FileIO.

Definition at line 460 of file Pic32mxUsbCdcDevice.cxx.

Member Data Documentation

◆ currentReadBuffer

unsigned Pic32mxCdc::currentReadBuffer
private

Index of the buffer for current (userspace) reads.

This buffer is considered full, even if it has zero bytes remaining. The steady state, when all input bytes are already consumed by the application layer, is that rxBuffer[currentReadBuffer] has zero bytes pending, rxPending is true, and rxBuffers[currentReadBuffer ^ 1] has its pointer submitted to the USB driver stack to receive the next urb from the host, whenever it comes.

Definition at line 217 of file Pic32mxUsbCdcDevice.cxx.

◆ deviceHandle

USB_DEVICE_HANDLE Pic32mxCdc::deviceHandle {USB_DEVICE_HANDLE_INVALID}
private

Equivalent of an fd for the USB core driver.

Definition at line 194 of file Pic32mxUsbCdcDevice.cxx.

◆ driverErrors

unsigned Pic32mxCdc::driverErrors
private

Counts internal error conditions that should not occur but we are hoping we can recover from them.

Definition at line 229 of file Pic32mxUsbCdcDevice.cxx.

◆ drvUSBObject

SYS_MODULE_OBJ Pic32mxCdc::drvUSBObject
private

Module pointer for USB core device.

Definition at line 190 of file Pic32mxUsbCdcDevice.cxx.

◆ irqVector

unsigned Pic32mxCdc::irqVector
private

unused.

Do not remove – needed to force linking in the interrupt trampoline.

Definition at line 233 of file Pic32mxUsbCdcDevice.cxx.

◆ isConfigured

unsigned Pic32mxCdc::isConfigured
private

true when we have a configured host.

Definition at line 209 of file Pic32mxUsbCdcDevice.cxx.

◆ isEnabled

unsigned Pic32mxCdc::isEnabled
private

True when we have open fds.

Definition at line 205 of file Pic32mxUsbCdcDevice.cxx.

◆ lineCodingData

USB_CDC_LINE_CODING Pic32mxCdc::lineCodingData
private

Holds last set line coding data that came from the host.

Definition at line 196 of file Pic32mxUsbCdcDevice.cxx.

◆ needAttach

unsigned Pic32mxCdc::needAttach
private

true wehen we need to execute an attach command on the usb task.

Definition at line 207 of file Pic32mxUsbCdcDevice.cxx.

◆ nextReadBufferFull

unsigned Pic32mxCdc::nextReadBufferFull
private

true if the opposite read buffer (the one after current) also has data.

If this is true, then rxPending cannot be true.

Definition at line 222 of file Pic32mxUsbCdcDevice.cxx.

◆ readHandle

USB_DEVICE_CDC_TRANSFER_HANDLE Pic32mxCdc::readHandle
private

Handle for the current pending read.

Definition at line 198 of file Pic32mxUsbCdcDevice.cxx.

◆ RX_DEVICEBUFFER_SIZE

constexpr unsigned Pic32mxCdc::RX_DEVICEBUFFER_SIZE = 0
staticconstexprprivate

Definition at line 128 of file Pic32mxUsbCdcDevice.cxx.

◆ rxBuffers

DeviceBuffer<uint8_t>* Pic32mxCdc::rxBuffers[2]
private

Receive buffers.

We have these separate from Serial, because we need to use double buffering with the USB middleware; specifically we always need to provide a free 64-byte buffer for the read command.

Definition at line 238 of file Pic32mxUsbCdcDevice.cxx.

◆ rxPending

unsigned Pic32mxCdc::rxPending
private

true when we have an outstanding read request with the USB driver.

Definition at line 219 of file Pic32mxUsbCdcDevice.cxx.

◆ TX_BUFFER_SIZE

constexpr unsigned Pic32mxCdc::TX_BUFFER_SIZE = 3 * USB_CDC_BUFFER_SIZE
staticconstexprprivate

Definition at line 127 of file Pic32mxUsbCdcDevice.cxx.

◆ txPendingBytes

unsigned Pic32mxCdc::txPendingBytes
private

Zero if no writes are pending, otherwise the number of bytes we sent with the pending write to the USB device driver.

Definition at line 225 of file Pic32mxUsbCdcDevice.cxx.

◆ USB_CDC_BUFFER_SIZE

constexpr unsigned Pic32mxCdc::USB_CDC_BUFFER_SIZE = 64
staticconstexprprivate

Definition at line 125 of file Pic32mxUsbCdcDevice.cxx.

◆ usbDevObject0

SYS_MODULE_OBJ Pic32mxCdc::usbDevObject0
private

Module pointer for USB middleware device.

Definition at line 192 of file Pic32mxUsbCdcDevice.cxx.

◆ writeHandle

USB_DEVICE_CDC_TRANSFER_HANDLE Pic32mxCdc::writeHandle
private

Handle for the current pending write.

Definition at line 200 of file Pic32mxUsbCdcDevice.cxx.


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