diff options
Diffstat (limited to 'src/dev/serial/serial.hh')
-rw-r--r-- | src/dev/serial/serial.hh | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/dev/serial/serial.hh b/src/dev/serial/serial.hh new file mode 100644 index 000000000..230ecaa74 --- /dev/null +++ b/src/dev/serial/serial.hh @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2014, 2017 ARM Limited + * All rights reserved + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Authors: Andreas Sandberg + */ + +#ifndef __DEV_SERIAL_HH__ +#define __DEV_SERIAL_HH__ + +#include "base/callback.hh" +#include "sim/sim_object.hh" + +struct SerialDeviceParams; +struct SerialNullDeviceParams; + +/** + * Base class for serial devices such as terminals. + * + * This class provides a unified interface that all serial (RS232 or + * similar) devices must implement. A device can be wired to exactly + * one host serial interface (serial port model). + * + * SerialDevices are passive devices that are <i>driven</i> by the + * serial interface using the writeData(c) (the interface sends a + * character) and readData() (the interface reads a character) + * methods. Serial devices need to override these methods to + * communicate with the host interface layer. + * + * To implement basic flow control, serial devices must implement the + * dataAvailable() method. This method returns true if a valid + * character can be read using the readData() method. When data + * becomes available, the serial device must call the + * notifyInterface() method to send a callback to the interface layer. + * + * To send a character (host to device), the interface layer calls + * writeData(char) to send a character to the serial device. + * + * To read a character (device to host), the interface layer calls + * dataAvailable() to determine if there is a character pending. If + * there is data available, it immediately calls readData() to get the + * character. The receive loop in the serial device typically looks + * like this: + * + * \code{.cc} + * while (device.dataAvailable()) { + * printf("%c", (int)device.readData()); + * } + * \endcode + * + * To avoid polling, the interface layer may register a data available + * callback using the regInterfaceCallback() method. The device uses + * this callback to notify the interface layer whenever there is new + * data pending. Note that devices will normally only notify the + * interface layer when there is a state transition in the + * device. E.g., the dataAvailable() transitions from false to + * true. This means that there can be multiple pending characters when + * the interface layer receives the callback. + */ +class SerialDevice : public SimObject +{ + public: + SerialDevice(const SerialDeviceParams *p); + ~SerialDevice(); + + public: // Serial device API (UART->Device) + /** + * Register a data available callback into the host interface layer. + * + * Serial devices need to call the underlying host interface layer + * to inform it of state change such as pending data that can be + * read from the device by the interface layer using the readData() + * method. The interface layer may use this method to register a + * callback that informs it of pending data. + * + * @param c Callback instance from interface layer. + */ + void regInterfaceCallback(Callback *c); + + /** + * Check if there is pending data from the serial device. + * + * @return true if there is data pending that can be read using + * the readData() method. + */ + virtual bool dataAvailable() const = 0; + + /** + * Transmit a character from the host interface to the device. + * + * @param c Received data. + */ + virtual void writeData(uint8_t c) = 0; + + /** + * Read a character from the device. + * + * @return Character from the device's output buffer, undefined if + * no data is pending. + */ + virtual uint8_t readData() = 0; + + protected: + /** Notify the host interface of pending data. */ + void notifyInterface(); + + private: + /** Currently regisxtered host interface layer callback */ + Callback *interfaceCallback; +}; + +/** + * Dummy serial device that discards all data sent to it. + */ +class SerialNullDevice : public SerialDevice +{ + public: + SerialNullDevice(const SerialNullDeviceParams *p); + + public: + bool dataAvailable() const override { return false; } + void writeData(uint8_t c) override {}; + uint8_t readData() override; +}; + +#endif // __DEV_SERIAL_HH__ |