FreeNOS
NS16550.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2019 Niek Linnenbank
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <FreeNOS/Constant.h>
19 #include <FreeNOS/User.h>
20 #include "NS16550.h"
21 
23 {
24  return new NS16550(UART0_IRQ);
25 }
26 
28  : SerialDevice(irq)
29 {
30  m_identifier << "serial0";
31 }
32 
34 {
35  if (!isKernel)
36  {
37  // Remap IO base to ensure we have user-level access to the registers.
38  if (m_io.map(UART_BASE, PAGESIZE*2,
40  != IO::Success)
41  {
42  return FileSystem::IOError;
43  }
44 
45  // Disable receiving interrupts
47  }
48  else
49  {
50  m_io.setBase(UART_BASE);
51  }
52 
53  // Set integer & fractional part of baud rate.
54  setDivisorLatch(true);
57  setDivisorLatch(false);
58 
59  // Use 8 bit data transmission, 1 stop bit, no parity
61 
62  if (isKernel)
63  {
64  // Mask all interrupts.
66  }
67  else
68  {
69  // Enable Rx/Tx interrupts and FIFOs
73  }
74 
75  return FileSystem::Success;
76 }
77 
79 {
80  // Mask interrupt until FIFOs are empty
82  return FileSystem::Success;
83 }
84 
86  Size & size,
87  const Size offset)
88 {
89  Size bytes = 0;
90 
91  // Read as much bytes as possible
92  while ((m_io.read(LineStatus) & LineStatusDataReady) && bytes < size)
93  {
94  u8 byte = m_io.read(ReceiveBuffer);
95  buffer.bufferedWrite(&byte, 1);
96  bytes++;
97  }
98 
99  // Re-enable interrupts
100  if (!isKernel)
101  {
103  {
106  }
107  }
108 
109  if (buffer.getCount())
110  {
111  size = buffer.getCount();
112  return FileSystem::Success;
113  }
114  else
115  {
116  return FileSystem::RetryAgain;
117  }
118 }
119 
121  Size & size,
122  const Size offset)
123 {
124  Size bytes = 0;
125 
126  // Write as much bytes as possible
127  while (bytes < size)
128  {
129  // Wait until TX fifo is empty
130  while (!(m_io.read(LineStatus) & LineStatusTxEmpty))
131  {
132  ;
133  }
134 
135  m_io.write(TransmitHolding, buffer[bytes++]);
136  }
137 
138  if (bytes)
139  {
140  size = bytes;
141  return FileSystem::Success;
142  }
143  else
144  {
145  return FileSystem::RetryAgain;
146  }
147 }
148 
149 void NS16550::setDivisorLatch(bool enabled)
150 {
151  // Set the divisor latch register
152  u32 lc = m_io.read(LineControl);
153 
154  if (enabled)
156  else
158 
159  m_io.write(LineControl, lc);
160 }
NS16550::LineControlDivisorLatch
@ LineControlDivisorLatch
Definition: NS16550.h:81
NS16550::DivisorLatchHigh
@ DivisorLatchHigh
Definition: NS16550.h:50
NS16550::InterruptEnable
@ InterruptEnable
Definition: NS16550.h:51
NS16550::LineStatusDataReady
@ LineStatusDataReady
Definition: NS16550.h:88
IOBuffer::getCount
Size getCount() const
Get byte count.
Definition: IOBuffer.cpp:109
EnableIRQ
@ EnableIRQ
Definition: ProcessCtl.h:44
NS16550::interrupt
virtual FileSystem::Result interrupt(const Size vector)
Called when an interrupt has been triggered for this device.
Definition: NS16550.cpp:78
Memory::Writable
@ Writable
Definition: Memory.h:42
IO::map
Result map(Address phys, Size size=4096, Memory::Access access=Memory::Readable|Memory::Writable|Memory::User)
Map I/O address space.
Definition: IO.cpp:38
SerialDevice::m_io
Arch::IO m_io
I/O instance.
Definition: SerialDevice.h:65
Memory::User
@ User
Definition: Memory.h:44
ARMIO::write
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition: ARMIO.h:46
PAGESIZE
#define PAGESIZE
ARM uses 4K pages.
Definition: ARMConstant.h:97
NS16550.h
IOBuffer::bufferedWrite
FileSystem::Result bufferedWrite(const void *buffer, const Size size)
Buffered write bytes to the I/O buffer.
Definition: IOBuffer.cpp:146
isKernel
C uint isKernel
Non-zero if this executable is linked as the kernel.
NS16550::write
virtual FileSystem::Result write(IOBuffer &buffer, Size &size, const Size offset)
Write bytes to the device.
Definition: NS16550.cpp:120
Memory::Device
@ Device
Definition: Memory.h:48
FileSystem::IOError
@ IOError
Definition: FileSystem.h:58
NS16550::TransmitHolding
@ TransmitHolding
Definition: NS16550.h:48
FileSystem::Success
@ Success
Definition: FileSystem.h:54
ProcessCtl
API::Result ProcessCtl(const ProcessID proc, const ProcessOperation op, const Address addr=0, const Address output=0)
Prototype for user applications.
Definition: ProcessCtl.h:93
NS16550::FifoControlEnable
@ FifoControlEnable
Definition: NS16550.h:76
Memory::Readable
@ Readable
Definition: Memory.h:41
NS16550::ReceiveBuffer
@ ReceiveBuffer
Definition: NS16550.h:47
NS16550::FifoControlTrigger1
@ FifoControlTrigger1
Definition: NS16550.h:75
NS16550::LineStatusTxEmpty
@ LineStatusTxEmpty
Definition: NS16550.h:87
SELF
#define SELF
Definition: ProcessID.h:35
NS16550::LineControl
@ LineControl
Definition: NS16550.h:54
IO::setBase
void setBase(const Address base)
Set memory I/O base offset.
Definition: IO.cpp:33
IOBuffer
Abstract Input/Output buffer.
Definition: IOBuffer.h:37
u32
unsigned int u32
Unsigned 32-bit number.
Definition: Types.h:53
Size
unsigned int Size
Any sane size indicator cannot go negative.
Definition: Types.h:128
AbstractFactory::create
static T * create()
Abstract function to create an instance of T.
ARMIO::read
u32 read(u32 reg) const
read from memory mapped I/O register
Definition: ARMIO.h:62
SerialDevice
Provides sequential byte stream of incoming (RX) and outgoing (TX) data.
Definition: SerialDevice.h:37
IO::Success
@ Success
Definition: IO.h:44
NS16550::DivisorLatchLow
@ DivisorLatchLow
Definition: NS16550.h:49
Device::m_identifier
String m_identifier
Unique identifier for this Device.
Definition: Device.h:79
NS16550::LineStatus
@ LineStatus
Definition: NS16550.h:56
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
NS16550::NS16550
NS16550(const u32 irq)
Constructor.
Definition: NS16550.cpp:27
FileSystem::RetryAgain
@ RetryAgain
Definition: FileSystem.h:57
NS16550::initialize
virtual FileSystem::Result initialize()
Initializes the UART.
Definition: NS16550.cpp:33
NS16550::setDivisorLatch
void setDivisorLatch(bool enabled)
Enable access to the divisor latch registers.
Definition: NS16550.cpp:149
NS16550::FifoControl
@ FifoControl
Definition: NS16550.h:53
DisableIRQ
@ DisableIRQ
Definition: ProcessCtl.h:45
SerialDevice::m_irq
const u32 m_irq
interrupt vector
Definition: SerialDevice.h:62
NS16550::ReceiveDataInterrupt
@ ReceiveDataInterrupt
Definition: NS16550.h:65
NS16550::read
virtual FileSystem::Result read(IOBuffer &buffer, Size &size, const Size offset)
Read bytes from the device.
Definition: NS16550.cpp:85
NS16550::LineControl8Bits
@ LineControl8Bits
Definition: NS16550.h:82
NS16550
The NS16550 is a commonly available UART device.
Definition: NS16550.h:38