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 {
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
76}
77
79{
80 // Mask interrupt until FIFOs are empty
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 {
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
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 {
146 }
147}
148
149void NS16550::setDivisorLatch(bool enabled)
150{
151 // Set the divisor latch register
152 u32 lc = m_io.read(LineControl);
153
154 if (enabled)
156 else
157 lc &= ~LineControlDivisorLatch;
158
160}
void write(u32 reg, u32 data)
write to memory mapped I/O register
Definition ARMIO.h:46
u32 read(u32 reg) const
read from memory mapped I/O register
Definition ARMIO.h:62
static T * create()
Abstract function to create an instance of T.
String m_identifier
Unique identifier for this Device.
Definition Device.h:79
Abstract Input/Output buffer.
Definition IOBuffer.h:38
Size getCount() const
Get byte count.
Definition IOBuffer.cpp:109
FileSystem::Result bufferedWrite(const void *buffer, const Size size)
Buffered write bytes to the I/O buffer.
Definition IOBuffer.cpp:146
void setBase(const Address base)
Set memory I/O base offset.
Definition IO.cpp:33
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
@ Success
Definition IO.h:44
The NS16550 is a commonly available UART device.
Definition NS16550.h:39
NS16550(const u32 irq)
Constructor.
Definition NS16550.cpp:27
virtual FileSystem::Result interrupt(const Size vector)
Called when an interrupt has been triggered for this device.
Definition NS16550.cpp:78
@ ReceiveDataInterrupt
Definition NS16550.h:65
virtual FileSystem::Result initialize()
Initializes the UART.
Definition NS16550.cpp:33
@ LineStatusDataReady
Definition NS16550.h:88
@ LineStatusTxEmpty
Definition NS16550.h:87
@ LineControl
Definition NS16550.h:54
@ TransmitHolding
Definition NS16550.h:48
@ ReceiveBuffer
Definition NS16550.h:47
@ LineStatus
Definition NS16550.h:56
@ InterruptEnable
Definition NS16550.h:51
@ DivisorLatchLow
Definition NS16550.h:49
@ DivisorLatchHigh
Definition NS16550.h:50
@ FifoControl
Definition NS16550.h:53
@ LineControl8Bits
Definition NS16550.h:82
@ LineControlDivisorLatch
Definition NS16550.h:81
virtual FileSystem::Result read(IOBuffer &buffer, Size &size, const Size offset)
Read bytes from the device.
Definition NS16550.cpp:85
virtual FileSystem::Result write(IOBuffer &buffer, Size &size, const Size offset)
Write bytes to the device.
Definition NS16550.cpp:120
@ FifoControlTrigger1
Definition NS16550.h:75
@ FifoControlEnable
Definition NS16550.h:76
void setDivisorLatch(bool enabled)
Enable access to the divisor latch registers.
Definition NS16550.cpp:149
Provides sequential byte stream of incoming (RX) and outgoing (TX) data.
const u32 m_irq
interrupt vector
Arch::IO m_io
I/O instance.
#define SELF
Definition ProcessID.h:35
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
@ DisableIRQ
Definition ProcessCtl.h:45
@ EnableIRQ
Definition ProcessCtl.h:44
#define PAGESIZE
ARM uses 4K pages.
Definition ARMConstant.h:97
C uint isKernel
Non-zero if this executable is linked as the kernel.
unsigned int u32
Unsigned 32-bit number.
Definition Types.h:53
unsigned int Size
Any sane size indicator cannot go negative.
Definition Types.h:128
unsigned char u8
Unsigned 8-bit number.
Definition Types.h:59
Result
Result code for filesystem Actions.
Definition FileSystem.h:53
@ User
Definition Memory.h:44
@ Readable
Definition Memory.h:41
@ Device
Definition Memory.h:48
@ Writable
Definition Memory.h:42