gem5 v24.0.0.0
Loading...
Searching...
No Matches
uart8250.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
34
35#include <string>
36#include <vector>
37
38#include "base/inifile.hh"
39#include "base/trace.hh"
40#include "debug/Uart.hh"
41#include "dev/platform.hh"
42#include "mem/packet.hh"
43#include "mem/packet_access.hh"
44#include "sim/serialize.hh"
45
46namespace gem5
47{
48
49void
51{
52 if (intrBit & registers.ier.get()) {
53 DPRINTF(Uart, "UART InterEvent, interrupting\n");
54 platform->postConsoleInt();
55 status |= intrBit;
57 } else {
58 DPRINTF(Uart, "UART InterEvent, not interrupting\n");
59 }
60}
61
62/* The linux serial driver (8250.c about line 1182) loops reading from
63 * the device until the device reports it has no more data to
64 * read. After a maximum of 255 iterations the code prints "serial8250
65 * too much work for irq X," and breaks out of the loop. Since the
66 * simulated system is so much slower than the actual system, if a
67 * user is typing on the keyboard it is very easy for them to provide
68 * input at a fast enough rate to not allow the loop to exit and thus
69 * the error to be printed. This magic number provides a delay between
70 * the time the UART receives a character to send to the simulated
71 * system and the time it actually notifies the system it has a
72 * character to send to alleviate this problem. --Ali
73 */
74void
76{
77 static const Tick interval = 225 * sim_clock::as_int::ns;
78 DPRINTF(Uart, "Scheduling IER interrupt for %s, at cycle %lld\n",
79 event->name(), curTick() + interval);
80 if (!event->scheduled()) {
81 schedule(event, curTick() + interval);
82 } else {
83 reschedule(event, curTick() + interval);
84 }
85}
86
87void
89{
90 if ((status & intrBit) == 0) {
91 return;
92 }
93 status &= ~intrBit;
94
95 // Clear interrupt at the controller if neither TX nor RX is pending now
96 if (!status) {
97 platform->clearConsoleInt();
98 }
99}
100
102 : Uart(p, p.pio_size), registers(this, name() + ".registers"),
103 lastTxInt(0),
104 txIntrEvent([this]{ processIntrEvent(TX_INT); }, "TX"),
105 rxIntrEvent([this]{ processIntrEvent(RX_INT); }, "RX")
106{
107}
108
109Uart8250::Registers::Registers(Uart8250 *uart, const std::string &new_name) :
110 RegisterBankLE(new_name, 0), rbrThr(rbr, thr), rbrThrDll(rbrThr, dll),
111 ierDlh(ier, dlh), iirFcr(iir, fcr)
112{
113 rbr.reader(uart, &Uart8250::readRbr);
114 thr.writer(uart, &Uart8250::writeThr);
115 ier.writer(uart, &Uart8250::writeIer);
116 iir.reader(uart, &Uart8250::readIir);
117
118 lcr.writer([this](auto &reg, const auto &value) {
119 reg.update(value);
120 rbrThrDll.select(value.dlab);
121 ierDlh.select(value.dlab);
122 });
123
124 mcr.writer([](auto &reg, const auto &value) {
125 if (value == (UART_MCR_LOOP | 0x0A))
126 reg.update(0x9A);
127 });
128
129 lsr.readonly().
130 reader([device = uart->device](auto &reg) {
131 Lsr lsr = 0;
132 if (device->dataAvailable())
133 lsr.rdr = 1;
134 lsr.tbe = 1;
135 lsr.txEmpty = 1;
136 return lsr;
137 });
138
139 msr.readonly();
140
142}
143
144uint8_t
146{
147 uint8_t data = 0;
148 if (device->dataAvailable()) {
149 data = device->readData();
150 } else {
151 DPRINTF(Uart, "empty read of RX register\n");
152 }
153
155
156 if (device->dataAvailable() && registers.ier.get().rdi) {
158 } else if (rxIntrEvent.scheduled()) {
159 // Must deschedule a future interrupt if there is no more data to read,
160 // otherwise this would confuse the kernel (iir.id=rx but lsr.rdr=0)
162 }
163
164 return data;
165}
166
167void
169{
172 if (registers.ier.get().thri) {
174 } else if (txIntrEvent.scheduled()) {
176 }
177}
178
179Uart8250::Iir
181{
182 DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status);
183
184 Iir iir = 0;
185 if (status & RX_INT) {
186 // Rx data interrupt has a higher priority.
187 iir.id = (uint8_t)InterruptIds::Rx;
188 } else if (status & TX_INT) {
189 iir.id = (uint8_t)InterruptIds::Tx;
190 // Tx interrupts are cleared on IIR reads.
191 if (txIntrEvent.scheduled()) {
193 }
195 } else {
196 iir.pending = 1;
197 }
198 return iir;
199}
200
201void
203{
204 reg.update(ier);
205
206 if (ier.thri) {
207 DPRINTF(Uart, "IER: IER_THRI set, scheduling TX intrrupt\n");
208 if (curTick() - lastTxInt > 225 * sim_clock::as_int::ns) {
209 DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n",
210 curTick(), lastTxInt);
212 } else {
213 DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n",
214 curTick(), lastTxInt);
216 }
217 } else {
218 DPRINTF(Uart, "IER: IER_THRI cleared, descheduling TX intrrupt\n");
219 if (txIntrEvent.scheduled()) {
221 }
223 }
224
225 if (ier.rdi && device->dataAvailable()) {
226 DPRINTF(Uart, "IER: IER_RDI set, scheduling RX intrrupt\n");
228 } else {
229 DPRINTF(Uart, "IER: IER_RDI cleared, descheduling RX intrrupt\n");
230 if (rxIntrEvent.scheduled()) {
232 }
234 }
235}
236
237Tick
239{
240 Addr daddr = pkt->getAddr() - pioAddr;
241
242 DPRINTF(Uart, "Read register %#x\n", daddr);
243
244 registers.read(daddr, pkt->getPtr<void>(), pkt->getSize());
245
246 pkt->makeAtomicResponse();
247 return pioDelay;
248}
249
250Tick
252{
253 Addr daddr = pkt->getAddr() - pioAddr;
254
255 DPRINTF(Uart, "Write register %#x value %#x\n", daddr,
256 pkt->getRaw<uint8_t>());
257
258 registers.write(daddr, pkt->getPtr<void>(), pkt->getSize());
259
260 pkt->makeAtomicResponse();
261 return pioDelay;
262}
263
264void
266{
267 // If the kernel wants an interrupt when we have data.
268 if (registers.ier.get().rdi) {
269 platform->postConsoleInt();
270 status |= RX_INT;
271 }
272}
273
276{
277 AddrRangeList ranges;
278 ranges.push_back(RangeSize(pioAddr, pioSize));
279 return ranges;
280}
281
282void
284{
286 paramOut(cp, "IER", registers.ier);
287 paramOut(cp, "LCR", registers.lcr);
288 paramOut(cp, "MCR", registers.mcr);
289 Tick rxintrwhen;
290 if (rxIntrEvent.scheduled()) {
291 rxintrwhen = rxIntrEvent.when();
292 } else {
293 rxintrwhen = 0;
294 }
295 Tick txintrwhen;
296 if (txIntrEvent.scheduled()) {
297 txintrwhen = txIntrEvent.when();
298 } else {
299 txintrwhen = 0;
300 }
301 SERIALIZE_SCALAR(rxintrwhen);
302 SERIALIZE_SCALAR(txintrwhen);
303}
304
305void
307{
309 paramIn(cp, "IER", registers.ier);
310 paramIn(cp, "LCR", registers.lcr);
311 paramIn(cp, "MCR", registers.mcr);
312 Tick rxintrwhen;
313 Tick txintrwhen;
314 UNSERIALIZE_SCALAR(rxintrwhen);
315 UNSERIALIZE_SCALAR(txintrwhen);
316 if (rxintrwhen != 0) {
317 schedule(rxIntrEvent, rxintrwhen);
318 }
319 if (txintrwhen != 0) {
320 schedule(txIntrEvent, txintrwhen);
321 }
322}
323
324} // namespace gem5
#define DPRINTF(x,...)
Definition trace.hh:210
const char data[]
Addr pioAddr
Address that the device listens to.
Definition io_device.hh:151
Tick pioDelay
Delay that the device experinces on an access.
Definition io_device.hh:157
Addr pioSize
Size that the device's address range.
Definition io_device.hh:154
virtual std::string name() const
Definition named.hh:47
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition packet.hh:295
Addr getAddr() const
Definition packet.hh:807
T * getPtr()
get a pointer to the data ptr.
Definition packet.hh:1225
unsigned getSize() const
Definition packet.hh:817
T getRaw() const
Get the data in the packet without byte swapping.
void makeAtomicResponse()
Definition packet.hh:1074
void addRegisters(std::initializer_list< RegisterAdder > adders)
Definition reg_bank.hh:956
virtual void read(Addr addr, void *buf, Addr bytes)
Definition reg_bank.hh:1029
virtual void write(Addr addr, const void *buf, Addr bytes)
Definition reg_bank.hh:1075
virtual uint8_t readData()=0
Read a character from the device.
virtual void writeData(uint8_t c)=0
Transmit a character from the host interface to the device.
virtual bool dataAvailable() const =0
Check if there is pending data from the serial device.
Register< Lcr > lcr
Definition uart8250.hh:195
Register< Ier > ier
Definition uart8250.hh:185
Register< Lsr > lsr
Definition uart8250.hh:197
BankedRegister ierDlh
Definition uart8250.hh:187
BankedRegister rbrThrDll
Definition uart8250.hh:182
Registers(Uart8250 *uart, const std::string &new_name)
Definition uart8250.cc:109
RWSwitchedRegister iirFcr
Definition uart8250.hh:192
Register< Iir > iir
Definition uart8250.hh:190
void clearIntr(int intrBit)
Definition uart8250.cc:88
Iir readIir(Register< Iir > &reg)
Definition uart8250.cc:180
EventFunctionWrapper txIntrEvent
Definition uart8250.hh:220
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition uart8250.cc:283
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition uart8250.cc:306
void writeThr(Register8 &reg, const uint8_t &data)
Definition uart8250.cc:168
Registers registers
Definition uart8250.hh:207
EventFunctionWrapper rxIntrEvent
Definition uart8250.hh:221
Uart8250Params Params
Definition uart8250.hh:224
void dataAvailable() override
Inform the uart that there is data available.
Definition uart8250.cc:265
Uart8250(const Params &p)
Definition uart8250.cc:101
AddrRangeList getAddrRanges() const override
Determine the address ranges that this device responds to.
Definition uart8250.cc:275
Tick write(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition uart8250.cc:251
void scheduleIntr(Event *event)
Definition uart8250.cc:75
Registers::Register< T > Register
Definition uart8250.hh:205
Tick read(PacketPtr pkt) override
Pure virtual function that the device must implement.
Definition uart8250.cc:238
Registers::Register8 Register8
Definition uart8250.hh:203
uint8_t readRbr(Register8 &reg)
Definition uart8250.cc:145
void processIntrEvent(int intrBit)
Definition uart8250.cc:50
void writeIer(Register< Ier > &reg, const Ier &ier)
Definition uart8250.cc:202
SerialDevice * device
Definition uart.hh:54
Platform * platform
Definition uart.hh:53
int status
Definition uart.hh:52
AddrRange RangeSize(Addr start, Addr size)
void deschedule(Event &event)
Definition eventq.hh:1021
bool scheduled() const
Determine if the current event is scheduled.
Definition eventq.hh:458
void schedule(Event &event, Tick when)
Definition eventq.hh:1012
void reschedule(Event &event, Tick when, bool always=false)
Definition eventq.hh:1030
Tick when() const
Get the time that the event is scheduled.
Definition eventq.hh:501
Declaration of IniFile object.
Bitfield< 10, 5 > event
Bitfield< 0 > p
Bitfield< 5, 3 > reg
Definition types.hh:92
Tick ns
nanosecond
Definition core.cc:68
Copyright (c) 2024 - Pranith Kumar Copyright (c) 2020 Inria All rights reserved.
Definition binary32.hh:36
const int RX_INT
Definition uart.hh:46
Tick curTick()
The universal simulation clock.
Definition cur_tick.hh:46
std::ostream CheckpointOut
Definition serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition types.hh:147
void paramOut(CheckpointOut &cp, const std::string &name, ExtMachInst const &machInst)
Definition types.cc:40
void paramIn(CheckpointIn &cp, const std::string &name, ExtMachInst &machInst)
Definition types.cc:72
uint64_t Tick
Tick count type.
Definition types.hh:58
const uint8_t UART_MCR_LOOP
Definition uart8250.hh:46
const int TX_INT
Definition uart.hh:47
Declaration of the Packet class.
Generic interface for platforms.
#define UNSERIALIZE_SCALAR(scalar)
Definition serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition serialize.hh:568
const std::string & name()
Definition trace.cc:48
Defines a 8250 UART.

Generated on Tue Jun 18 2024 16:24:03 for gem5 by doxygen 1.11.0