commit 6efd408f5738f59c359283307b8bdb01ce000b8f from: Aleksey Ryndin date: Wed Mar 01 18:47:41 2023 UTC WiP: UART (qemu virt) commit - ec901abe19e6762b61d8e24f6fd2cb9908af3b66 commit + 6efd408f5738f59c359283307b8bdb01ce000b8f blob - 67f1d76e8ad6a249e4f884caf869a7809509da93 blob + 54c864c23b19f0d497af0de3d21153bea3fae281 --- .gitignore +++ .gitignore @@ -1,4 +1,4 @@ **/*.o squat.elf squat.img -local.mk +config.mk blob - 05bcedef0d4e0cda55a63b8c080e810f9e31aacc blob + 513b64ee093fc2d7f756aae7ee1d58cdc3def308 --- Makefile +++ Makefile @@ -2,12 +2,13 @@ AS = clang CXX = clang++ LD = ld.lld OBJCOPY = llvm-objcopy --include local.mk ARCH = aarch64 TARGET = ${ARCH}-none-elf -BOARD = qemu_virt +BOARD = virt +-include config.mk + ASFLAGS = -target ${TARGET} ASFILES = boot.o @@ -18,7 +19,7 @@ CXXFILES = kernel.cc uart_${BOARD}.cc OBJS = ${ASFILES:.S=.o} ${CXXFILES:.cc=.o} -.PHONY: clean +.PHONY: clean gdbstub all: squat.img @@ -33,3 +34,7 @@ squat.elf: linker.ld ${OBJS} clean: rm -rf *.o squat.elf squat.img + +gdbstub: squat.img + qemu-system-${ARCH} -s -S -M ${BOARD} -cpu cortex-a53 \ + -kernel squat.img -nographic -monitor none -serial stdio blob - /dev/null blob + e5a8442da87eec7b52d8f5ddee52d77dd2028e32 (mode 644) --- /dev/null +++ include/pl011.h @@ -0,0 +1,73 @@ +// pl011.h + +#pragma once + +#include + + +namespace Pl011 { + + +enum Register { + DATA_REGISTER = 0x00, + FLAG_REGISTER = 0x18, + CONTROL_REGISTER = 0x30, +}; + + +struct FlagRegister { + union _U { + struct _Bits { + uint16_t m_ClearToSend : 1; + uint16_t m_DataSetReady : 1; + uint16_t m_DataCarrierDetect: 1; + uint16_t m_Busy : 1; + uint16_t m_ReceiveFifoEmpty : 1; + uint16_t m_TransmitFifoFull : 1; + uint16_t m_ReceiveFifoFull : 1; + uint16_t m_TransmitFifoEmpty: 1; + uint16_t m_RingIndicator : 1; + uint16_t m_ReservedZero : 7; + } m_Bits; + uint32_t m_nValue; + } m_u; + + explicit FlagRegister(uint32_t nValue = 0) + { + m_u.m_nValue = nValue; + } +}; +static_assert(sizeof(FlagRegister::_U::_Bits) == 2, "should be 2"); +static_assert(sizeof(FlagRegister) == 4, "should be 4"); + + +struct ControlRegister { + union _U { + struct _Bits { + uint16_t m_UartEnable : 1; + uint16_t m_SirEnable : 1; + uint16_t m_SirLowIrDaMode : 1; + uint16_t m_ReservedZero : 4; + uint16_t m_LoopbackEnable : 1; + uint16_t m_TransmitEnable : 1; + uint16_t m_ReceiveEnable : 1; + uint16_t m_DataTransmitReady: 1; + uint16_t m_RequestToSend : 1; + uint16_t m_Out1 : 1; + uint16_t m_Out2 : 1; + uint16_t m_RtsEnable : 1; + uint16_t m_CtsEnable : 1; + } m_Bits; + uint32_t m_nValue; + } m_u; + + ControlRegister() + { + m_u.m_nValue = 0; + } +}; +static_assert(sizeof(ControlRegister::_U::_Bits) == 2, "should be 2"); +static_assert(sizeof(ControlRegister) == 4, "should be 4"); + + +} // namespace Pl011 blob - eeae5fd55c128bd0f5a46cc928e3c0f248d90289 blob + a84a44765226a27452302bf120d891121f7c88be --- include/uart.h +++ include/uart.h @@ -13,7 +13,7 @@ void initialize(); void -send(uint8_t value); +send(uint8_t nValue); uint8_t recv(); blob - c4144f4f4f27dbfea85a4652e75c9fe9e952c475 blob + 33c10ac2df36f6d33dcfa9eb8fe5bc32918541d8 --- kernel.cc +++ kernel.cc @@ -23,10 +23,8 @@ void kernel_entry_point() { Board::Uart::initialize(); + uart_send_string("Squat entry point\r\n"); - - uart_send_string("Test ECHO mode\r\n"); - for (; ; ) - Board::Uart::send(Board::Uart::recv()); + ; } blob - 4bca98c1bdcfe706477e07f9e95f14ffc9468376 (mode 644) blob + /dev/null --- uart_qemu_virt.cc +++ /dev/null @@ -1,36 +0,0 @@ -// uart_qemu_virt.cc - - -#include -#include - - -namespace Board { -namespace Uart { - - -namespace { - -// constexpr uintptr_t UART_BASE = 0xffffffffc9000000ULL; - -} // anonymous namespace - - -void initialize() -{ -} - - -void send(uint8_t /*value*/) -{ -} - - -uint8_t recv() -{ - return 0; -} - - -} // namespace Uart -} // namespace Board blob - /dev/null blob + 78a76dc47a113d54d8f6d7fbbbb62dea9e81744f (mode 644) --- /dev/null +++ uart_virt.cc @@ -0,0 +1,50 @@ +// uart_virt.cc +// QEMU `virt` generic virtual platform + + +#include +#include +#include + + +namespace Board { +namespace Uart { + + +namespace { + +constexpr uintptr_t UART_BASE = 0xffffffffc9000000ULL; + +} // anonymous namespace + + +void initialize() +{ + Pl011::ControlRegister ControlRegister; + ControlRegister.m_u.m_Bits.m_UartEnable = 1; + ControlRegister.m_u.m_Bits.m_TransmitEnable = 1; + Hw::write32(UART_BASE + Pl011::CONTROL_REGISTER, ControlRegister.m_u.m_nValue); +} + + +void send(uint8_t nValue) +{ + // spin while fifo is full + for (; ; ) + { + Pl011::FlagRegister FlagRegister{Hw::read32(UART_BASE + Pl011::FLAG_REGISTER)}; + if (!FlagRegister.m_u.m_Bits.m_TransmitFifoFull) + break; + } + Hw::write32(UART_BASE + Pl011::DATA_REGISTER, nValue); +} + + +uint8_t recv() +{ + return 0; +} + + +} // namespace Uart +} // namespace Board