commit 6ed628b42830938a7919dd60f8af14519ce778f2 from: Aleksey Ryndin date: Mon Mar 18 13:34:01 2024 UTC Append uart_a64 (may be complete) commit - 69da5ffe1eeea1c4e88eaa4bbc4ce4ab4e296c94 commit + 6ed628b42830938a7919dd60f8af14519ce778f2 blob - e12fb16f4c3017b5c462c6b4c4b43279565a4098 blob + fb3b039ec6b295a04932f32082d51301caf35381 --- include/uart16550.h +++ include/uart16550.h @@ -8,6 +8,25 @@ 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 { @@ -54,6 +73,37 @@ struct FifoControlRegister { 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 @@ -22,18 +22,29 @@ constexpr auto CLOCK_DIVISOR = (SERIAL_CLOCK + (BAUDRA static_assert(CLOCK_DIVISOR == 13, "Should be 13"); +template +uint8_t read8() +{ + return Hw::read8(UART0_BASE + T::OFFSET); +} template T read() { - return T{Hw::read8(UART0_BASE + T::OFFSET)}; + return T{read8()}; } template +void write8(uint8_t nValue) +{ + Hw::write8(UART0_BASE + T::OFFSET, nValue); +} + +template void write(T Register) { - Hw::write8(UART0_BASE + T::OFFSET, Register.m_u.m_nValue); + write8(Register.m_u.m_nValue); } @@ -61,21 +72,43 @@ void initialize() 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(CLOCK_DIVISOR & 0xff); + write8((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()}; + if (LineStatusRegister.m_u.m_Bits.m_TxHoldingRegisterEmpty) + break; + } + write8(nValue); } uint8_t recv() { - // return Hw::read32(UART_BASE + Pl011::DATA_REGISTER) & 0xff; - return 0; + for (; ; ) + { + const auto LineStatusRegister{read()}; + if (LineStatusRegister.m_u.m_Bits.m_DataReady) + break; + } + return read8(); }