commit - 69da5ffe1eeea1c4e88eaa4bbc4ce4ab4e296c94
commit + 6ed628b42830938a7919dd60f8af14519ce778f2
blob - e12fb16f4c3017b5c462c6b4c4b43279565a4098
blob + fb3b039ec6b295a04932f32082d51301caf35381
--- include/uart16550.h
+++ include/uart16550.h
namespace Uart16550 {
+struct ReceiveBufferRegister {
+ static constexpr auto OFFSET = 0x00;
+};
+
+struct TransmitHoldingRegister {
+ static constexpr auto OFFSET = 0x00;
+};
+
+struct DivisorLatchLowRegister {
+ static constexpr auto OFFSET = 0x00;
+};
+
+
+
+struct DivisorLatchHighRegister {
+ static constexpr auto OFFSET = 0x04;
+};
+
+
struct InterruptEnableRegister {
union _U {
struct _Bits {
static_assert(sizeof(FifoControlRegister) == 1, "should be byte");
+struct LineControlRegister {
+ enum DataLengthSelect
+ {
+ BITS_5 = 0,
+ BITS_6 = 1,
+ BITS_7 = 2,
+ BITS_8 = 3,
+ };
+
+ union _U {
+ struct _Bits {
+ uint8_t m_DataLengthSelect : 2;
+ uint8_t m_NumberOfStopBits : 1;
+ uint8_t m_ParityEnable : 1;
+ uint8_t m_EvenParitySelect : 2;
+ uint8_t m_BreakControl : 1;
+ uint8_t m_DivisorLatchAccess: 1;
+ } m_Bits;
+ uint8_t m_nValue;
+ } m_u;
+
+ explicit LineControlRegister(uint8_t nValue = 0)
+ {
+ m_u.m_nValue = nValue;
+ }
+
+ static constexpr auto OFFSET = 0x0c;
+};
+static_assert(sizeof(LineControlRegister) == 1, "should be byte");
+
+
struct ModemControlRegister {
union _U {
struct _Bits {
blob - 2e8d89e89f1d6851336fc4fe2137e6450fdac72c
blob + 5c655aa36e41c08c9bb6f142c97148954713f1c9
--- uart_a64.cc
+++ uart_a64.cc
static_assert(CLOCK_DIVISOR == 13, "Should be 13");
+template <typename T>
+uint8_t read8()
+{
+ return Hw::read8(UART0_BASE + T::OFFSET);
+}
template <typename T>
T read()
{
- return T{Hw::read8(UART0_BASE + T::OFFSET)};
+ return T{read8<T>()};
}
template <typename T>
+void write8(uint8_t nValue)
+{
+ Hw::write8(UART0_BASE + T::OFFSET, nValue);
+}
+
+template <typename T>
void write(T Register)
{
- Hw::write8(UART0_BASE + T::OFFSET, Register.m_u.m_nValue);
+ write8<T>(Register.m_u.m_nValue);
}
FifoControlRegister.m_u.m_Bits.m_RcvrFifoReset = 1;
FifoControlRegister.m_u.m_Bits.m_XmitFifoReset = 1;
write(FifoControlRegister);
+
+ Uart16550::LineControlRegister LineControlRegister;
+ LineControlRegister.m_u.m_Bits.m_DataLengthSelect = Uart16550::LineControlRegister::BITS_8;
+ write(LineControlRegister);
+
+ LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 1;
+ write(LineControlRegister);
+
+ write8<Uart16550::DivisorLatchLowRegister>(CLOCK_DIVISOR & 0xff);
+ write8<Uart16550::DivisorLatchHighRegister>((CLOCK_DIVISOR >> 8) & 0xff);
+
+ LineControlRegister.m_u.m_Bits.m_DivisorLatchAccess = 0;
+ write(LineControlRegister);
}
void send(uint8_t nValue)
{
- (void)nValue;
- /* TBD! */
- // Hw::write32(UART_BASE + Pl011::DATA_REGISTER, nValue);
+ for (; ; )
+ {
+ const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
+ if (LineStatusRegister.m_u.m_Bits.m_TxHoldingRegisterEmpty)
+ break;
+ }
+ write8<Uart16550::TransmitHoldingRegister>(nValue);
}
uint8_t recv()
{
- // return Hw::read32(UART_BASE + Pl011::DATA_REGISTER) & 0xff;
- return 0;
+ for (; ; )
+ {
+ const auto LineStatusRegister{read<Uart16550::LineStatusRegister>()};
+ if (LineStatusRegister.m_u.m_Bits.m_DataReady)
+ break;
+ }
+ return read8<Uart16550::ReceiveBufferRegister>();
}