/* * 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 driven 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__