Uart now has correct write implementation presumably

This commit is contained in:
Yehowshua Immanuel 2025-02-26 01:51:33 -05:00
parent 8d5cd862ab
commit 024115e389
6 changed files with 41 additions and 29 deletions

View file

@ -8,6 +8,8 @@
static volatile bool ctrl_c_received = false; static volatile bool ctrl_c_received = false;
static char last_char = '\0'; static char last_char = '\0';
int is_char_available();
void sigint_handler(int sig_num) { void sigint_handler(int sig_num) {
ctrl_c_received = true; ctrl_c_received = true;
} }

View file

@ -1,22 +0,0 @@
./rv_tests/hello_world/hello.bin: file format binary
Disassembly of section .data:
0000000000000000 <.data>:
0: 00000597 auipc a1,0x0
4: 02458593 add a1,a1,36 # 0x24
8: 0005c503 lbu a0,0(a1)
c: 00050a63 beqz a0,0x20
10: 100002b7 lui t0,0x10000
14: 00a28023 sb a0,0(t0) # 0x10000000
18: 00158593 add a1,a1,1
1c: fedff06f j 0x8
20: 0000006f j 0x20
24: 6548 ld a0,136(a0)
26: 6c6c ld a1,216(s0)
28: 77202c6f jal s8,0x279a
2c: 646c726f jal tp,0xc7672
30: 0a21 add s4,s4,8
...

View file

@ -4,6 +4,7 @@ module Bus() where
import Clash.Prelude import Clash.Prelude
import Peripherals.Ram(Ram, RamLine, read, RamAddr) import Peripherals.Ram(Ram, RamLine, read, RamAddr)
import Peripherals.Uart(UartAddr, read)
import Machine(Peripherals(..)) import Machine(Peripherals(..))
import BusTypes( import BusTypes(
BusError(..), BusError(..),
@ -35,10 +36,19 @@ alignCheck addr SizeQuadWord = addr `mod` 16 == 0
read :: Request -> Peripherals -> IO ReadResponse read :: Request -> Peripherals -> IO ReadResponse
read (Request addr size) peripherals read (Request addr size) peripherals
| not (alignCheck addr size) = return $ ReadResponse $ Error UnAligned | not (alignCheck addr size) = return $ ReadResponse $ Error UnAligned
| (addr > ramStart) && (addr < ramEnd) = | (addr >= ramStart) && (addr <= ramEnd) =
return $ ReadResponse $ Result $ Peripherals.Ram.read size ramAddr (ram peripherals) return $
ReadResponse $
Result $ Peripherals.Ram.read size ramAddr (ram peripherals)
| (addr >= uartStart) && (addr <= uartEnd) =
ReadResponse . Result <$>
Peripherals.Uart.read size uartAddr
| otherwise = return $ ReadResponse $ Error UnMapped | otherwise = return $ ReadResponse $ Error UnMapped
where where
ramAddrNoOffset = addr - ramStart ramAddrNoOffset = addr - ramStart
ramAddr :: RamAddr ramAddr :: RamAddr
ramAddr = resize ramAddrNoOffset ramAddr = resize ramAddrNoOffset
uartAddrNoOffset = addr - uartStart
uartAddr :: UartAddr
uartAddr = resize uartAddrNoOffset

View file

@ -1,8 +1,8 @@
module Peripherals.Uart (read) where module Peripherals.Uart (read, write, UartAddr) where
import Clash.Prelude hiding (read) import Clash.Prelude hiding (read)
import Types (Byte) import Types (Byte)
import Data.Char (ord) import Data.Char (ord, chr)
import Peripherals.UartCFFI ( import Peripherals.UartCFFI (
initTerminal, initTerminal,
@ -20,6 +20,7 @@ import BusTypes (
ReadResponse(..), ReadResponse(..),
WriteResponse(..) WriteResponse(..)
) )
import GHC.Generics (URec(UAddr), Generic (from))
-- based on a 16550 UART which has an address space of 8 bytes -- based on a 16550 UART which has an address space of 8 bytes
type UartAddr = Unsigned 3 type UartAddr = Unsigned 3
@ -28,6 +29,9 @@ type UartAddr = Unsigned 3
rbrAddr :: UartAddr rbrAddr :: UartAddr
rbrAddr = 0x0 rbrAddr = 0x0
thrAddr :: UartAddr
thrAddr = 0x0
-- Line Status Register address -- Line Status Register address
lsrAddr :: UartAddr lsrAddr :: UartAddr
lsrAddr = 0x5 lsrAddr = 0x5
@ -50,8 +54,11 @@ buildRBR = do
-- Reads the Line Status Register (LSR) to check character availability -- Reads the Line Status Register (LSR) to check character availability
buildLSR :: IO Byte buildLSR :: IO Byte
buildLSR = do buildLSR = do
char_available <- isCharAvailable (char_available :: Byte) <- fromIntegral <$> isCharAvailable
return $ fromIntegral char_available -- highly unlikely that we overflow stdout buffer, so we set
-- transmit to always ready
let (transmit_ready :: Byte) = 0b0010_0000
return (char_available .|. transmit_ready)
-- Updated 'read' function to handle RBR and LSR reads -- Updated 'read' function to handle RBR and LSR reads
read :: TransactionSize -> UartAddr -> IO BusVal read :: TransactionSize -> UartAddr -> IO BusVal
@ -59,3 +66,18 @@ read size addr
| addr == rbrAddr = busValFromByte size <$> buildRBR | addr == rbrAddr = busValFromByte size <$> buildRBR
| addr == lsrAddr = busValFromByte size <$> buildLSR | addr == lsrAddr = busValFromByte size <$> buildLSR
| otherwise = return $ busValFromByte size 0x00 | otherwise = return $ busValFromByte size 0x00
extractLowestByte :: BusVal -> Byte
extractLowestByte (BusByte b) = b
extractLowestByte (BusHalfWord hw) = resize hw
extractLowestByte (BusFullWord fw) = resize fw
extractLowestByte (BusDoubleWord dw) = resize dw
extractLowestByte (BusQuadWord qw) = resize qw
byteToChar :: Byte -> Char
byteToChar = chr . fromIntegral
write :: BusVal -> UartAddr -> IO ()
write val addr
| addr == thrAddr = writeCharToTerminal $ byteToChar $ extractLowestByte val
| otherwise = return ()

View file

View file

@ -34,7 +34,7 @@ $(BIN): $(ELF)
# Run in QEMU # Run in QEMU
run: $(BIN) run: $(BIN)
echo "Press CTRL+A then X to exit QEMU" echo "Press CTRL+A then X to exit QEMU"
$(QEMU) -machine virt -nographic -bios none -kernel $(BIN) -device loader,file=$(BIN),addr=0x80000000 -device sifive_uart $(QEMU) -machine virt -nographic -bios none -kernel $(BIN) -device loader,file=$(BIN),addr=0x80000000
# Clean up generated files # Clean up generated files
clean: clean: