FreeNOS
PL011.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2015 Niek Linnenbank
3  * Copyright (C) 2013 Goswin von Brederlow <goswin-v-b@web.de>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <FreeNOS/Constant.h>
20 #include <FreeNOS/User.h>
21 #include "PL011.h"
22 
24 {
25  return new PL011(UART0_IRQ);
26 }
27 
28 PL011::PL011(const u32 irq)
29  : SerialDevice(irq)
30 {
31  m_identifier << "serial0";
32 }
33 
35 {
36  if (!isKernel)
37  {
38  // Remap IO base to ensure we have user-level access to the registers.
39  if (m_io.map(UART_BASE, PAGESIZE*2,
41  != IO::Success)
42  {
43  return FileSystem::IOError;
44  }
45 
46  // Disable receiving interrupts
48  }
49  else
50  {
51  m_io.setBase(UART_BASE);
52  }
53 
54  // Disable PL011.
55  m_io.write(PL011_CR, 0x00000000);
56 
57  // Clear pending interrupts.
58  m_io.write(PL011_ICR, 0x7FF);
59 
60  // Set integer & fractional part of baud rate.
61  m_io.write(PL011_IBRD, 26);
62  m_io.write(PL011_FBRD, 3);
63 
64  // Disable FIFO, use 8 bit data transmission, 1 stop bit, no parity
66 
67  if (isKernel)
68  {
69  // Mask all interrupts.
70  m_io.write(PL011_IMSC, (1 << 1) | (1 << 4) | (1 << 5) |
71  (1 << 6) | (1 << 7) | (1 << 8) |
72  (1 << 9) | (1 << 10));
73  }
74  else
75  {
76  // Enable Rx/Tx interrupts
79  }
80 
81  // Enable PL011, receive & transfer part of UART.
82  m_io.write(PL011_CR, (1 << 0) | (1 << 8) | (1 << 9));
83 
84  return FileSystem::Success;
85 }
86 
88 {
89  // Clear Receive Interrupts
90  u32 mis = m_io.read(PL011_MIS);
91  if (mis & PL011_MIS_RXMIS)
93 
94  // Clear Transmit Interrupts
95  mis = m_io.read(PL011_MIS);
96  if (mis & PL011_MIS_TXMIS)
98 
99  // Re-enable interrupts
100  if (!isKernel)
101  {
103  }
104 
105  return FileSystem::Success;
106 }
107 
109  Size & size,
110  const Size offset)
111 {
112  Size bytes = 0;
113 
114  // Clear Receive Interrupts
115  u32 mis = m_io.read(PL011_MIS);
116  if (mis & PL011_MIS_RXMIS)
118 
119  // Read as much bytes as possible
120  while (!(m_io.read(PL011_FR) & PL011_FR_RXFE) && bytes < size)
121  {
122  //buffer[bytes++] = m_io.read(PL011_DR);
123  u8 byte = m_io.read(PL011_DR);
124  buffer.bufferedWrite(&byte, 1);
125  bytes++;
126  }
127 
128  if (buffer.getCount())
129  {
130  size = buffer.getCount();
131  return FileSystem::Success;
132  }
133  else
134  {
135  return FileSystem::RetryAgain;
136  }
137 }
138 
140  Size & size,
141  const Size offset)
142 {
143  Size bytes = 0;
144 
145  // Clear Transmit Interrupts
146  u32 mis = m_io.read(PL011_MIS);
147  if (mis & PL011_MIS_TXMIS)
149 
150  // Write as much bytes as possible
151  while (bytes < size)
152  {
154  {
155  m_io.write(PL011_DR, buffer[bytes++]);
156  }
157  }
158 
159  if (bytes)
160  {
161  size = bytes;
162  return FileSystem::Success;
163  }
164  else
165  {
166  return FileSystem::RetryAgain;
167  }
168 }
PL011::write
virtual FileSystem::Result write(IOBuffer &buffer, Size &size, const Size offset)
Write bytes to the device.
Definition: PL011.cpp:139
PL011::PL011_DR
@ PL011_DR
Definition: PL011.h:47
PL011
The PL011 is a commonly available UART device frequently found in ARM systems.
Definition: PL011.h:39
IOBuffer::getCount
Size getCount() const
Get byte count.
Definition: IOBuffer.cpp:109
PL011::PL011_LCRH
@ PL011_LCRH
Definition: PL011.h:58
EnableIRQ
@ EnableIRQ
Definition: ProcessCtl.h:44
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
PL011::PL011_IMSC_RXIM
@ PL011_IMSC_RXIM
Definition: PL011.h:65
PL011::PL011
PL011(const u32 irq)
Constructor.
Definition: PL011.cpp:28
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.
Memory::Device
@ Device
Definition: Memory.h:48
FileSystem::IOError
@ IOError
Definition: FileSystem.h:58
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
PL011::PL011_CR
@ PL011_CR
Definition: PL011.h:61
PL011::PL011_FR_RXFE
@ PL011_FR_RXFE
Definition: PL011.h:51
PL011::PL011_FBRD
@ PL011_FBRD
Definition: PL011.h:56
PL011::PL011_ICR
@ PL011_ICR
Definition: PL011.h:74
Memory::Readable
@ Readable
Definition: Memory.h:41
SELF
#define SELF
Definition: ProcessID.h:35
IO::setBase
void setBase(const Address base)
Set memory I/O base offset.
Definition: IO.cpp:33
PL011::PL011_FR
@ PL011_FR
Definition: PL011.h:50
PL011::PL011_IBRD
@ PL011_IBRD
Definition: PL011.h:55
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
PL011::PL011_ICR_RXIC
@ PL011_ICR_RXIC
Definition: PL011.h:76
PL011::PL011_IMSC
@ PL011_IMSC
Definition: PL011.h:64
PL011::PL011_LCRH_WLEN_8BIT
@ PL011_LCRH_WLEN_8BIT
Definition: PL011.h:59
SerialDevice
Provides sequential byte stream of incoming (RX) and outgoing (TX) data.
Definition: SerialDevice.h:37
PL011::PL011_MIS
@ PL011_MIS
Definition: PL011.h:70
IO::Success
@ Success
Definition: IO.h:44
Device::m_identifier
String m_identifier
Unique identifier for this Device.
Definition: Device.h:79
PL011::PL011_MIS_RXMIS
@ PL011_MIS_RXMIS
Definition: PL011.h:71
FileSystem::Result
Result
Result code for filesystem Actions.
Definition: FileSystem.h:52
u8
unsigned char u8
Unsigned 8-bit number.
Definition: Types.h:59
FileSystem::RetryAgain
@ RetryAgain
Definition: FileSystem.h:57
PL011::interrupt
virtual FileSystem::Result interrupt(const Size vector)
Called when an interrupt has been triggered for this device.
Definition: PL011.cpp:87
PL011::PL011_MIS_TXMIS
@ PL011_MIS_TXMIS
Definition: PL011.h:72
PL011::read
virtual FileSystem::Result read(IOBuffer &buffer, Size &size, const Size offset)
Read bytes from the device.
Definition: PL011.cpp:108
PL011::initialize
virtual FileSystem::Result initialize()
Initializes the UART.
Definition: PL011.cpp:34
PL011::PL011_FR_TXFE
@ PL011_FR_TXFE
Definition: PL011.h:52
PL011::PL011_ICR_TXIC
@ PL011_ICR_TXIC
Definition: PL011.h:75
DisableIRQ
@ DisableIRQ
Definition: ProcessCtl.h:45
PL011.h
SerialDevice::m_irq
const u32 m_irq
interrupt vector
Definition: SerialDevice.h:62