DRAM access integration preparation
parent
383c68bfc9
commit
ab001bdc6d
|
@ -2,5 +2,5 @@ build/*
|
|||
__pycache__/*
|
||||
backup/*
|
||||
software/build/*
|
||||
hd_errors/*
|
||||
helpers/__pycache__/*
|
||||
modules/__pycache__/*
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"args": ["--build",
|
||||
//"--load", // May be used separately ...
|
||||
"--flash", // May be used separately ...
|
||||
"--load", // May be used separately ...
|
||||
//"--flash", // May be used separately ...
|
||||
"--revision=7.0",
|
||||
"--uart-name=crossover",
|
||||
//"--with-ethernet", // Not to be used together w/ etherbone! Won't TFTP ...
|
||||
|
|
|
@ -59,7 +59,7 @@ After installation of the relevant toolchains:
|
|||
5. Press reset on the board, the LED chain should become illuminated
|
||||
6. To program this base logic permanently, the board has to be improved, add a capacitor to stabilize the voltage for FPGA
|
||||
programming (see Wolfgang's documentation on https://git.hacknology.de/wolfgang/colorlight )
|
||||
7. Now run the same sequence as mentioned above, this time replacing the --load option with the --flash option
|
||||
7. Now run the same sequence as mentioned above, replacing the --load option with the --flash option
|
||||
8. This time it will take even longer ...
|
||||
9. And hopefully complete without errors. If successful, the basic ROM s/w is now in place & operating. In case of errors try again - rule out EMI disturbances if nec.
|
||||
10. Create the actual documentation for html via: 'sphinx-build -b html build/documentation build/documentation/html'
|
||||
|
|
|
@ -0,0 +1,258 @@
|
|||
#
|
||||
# This file is part of LiteDRAM.
|
||||
#
|
||||
# Copyright (c) 2015 Sebastien Bourdeauducq <sb@m-labs.hk>
|
||||
# Copyright (c) 2016-2019 Florent Kermarrec <florent@enjoy-digital.fr>
|
||||
# Copyright (c) 2018 John Sully <john@csquare.ca>
|
||||
# Copyright (c) 2016 Tim 'mithro' Ansell <mithro@mithis.com>
|
||||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
"""Direct Memory Access (DMA) reader and writer modules."""
|
||||
|
||||
from migen import *
|
||||
|
||||
from litex.soc.interconnect.csr import *
|
||||
from litex.soc.interconnect import stream
|
||||
|
||||
from litedram.common import LiteDRAMNativePort
|
||||
from litedram.frontend.axi import LiteDRAMAXIPort
|
||||
|
||||
# LiteDRAMDMAReader --------------------------------------------------------------------------------
|
||||
|
||||
class LiteDRAMDMAReader(Module, AutoCSR):
|
||||
"""Read data from DRAM memory.
|
||||
|
||||
For every address written to the sink, one DRAM word will be produced on
|
||||
the source.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
port : port
|
||||
Port on the DRAM memory controller to read from (Native or AXI).
|
||||
|
||||
fifo_depth : int
|
||||
How many request results the output FIFO can contain (and thus how many
|
||||
read requests can be outstanding at once).
|
||||
|
||||
fifo_buffered : bool
|
||||
Implement FIFO in Block Ram.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
sink : Record("address")
|
||||
Sink for DRAM addresses to be read.
|
||||
|
||||
source : Record("data")
|
||||
Source for DRAM word results from reading.
|
||||
|
||||
rsv_level: Signal()
|
||||
FIFO reservation level counter
|
||||
"""
|
||||
|
||||
def __init__(self, port, fifo_depth=16, fifo_buffered=False):
|
||||
assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort))
|
||||
self.port = port
|
||||
self.sink = sink = stream.Endpoint([("address", port.address_width)])
|
||||
self.source = source = stream.Endpoint([("data", port.data_width)])
|
||||
|
||||
# # #
|
||||
|
||||
# Native / AXI selection
|
||||
is_native = isinstance(port, LiteDRAMNativePort)
|
||||
is_axi = isinstance(port, LiteDRAMAXIPort)
|
||||
if is_native:
|
||||
(cmd, rdata) = port.cmd, port.rdata
|
||||
elif is_axi:
|
||||
(cmd, rdata) = port.ar, port.r
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
# Request issuance -------------------------------------------------------------------------
|
||||
request_enable = Signal()
|
||||
request_issued = Signal()
|
||||
|
||||
if is_native:
|
||||
self.comb += cmd.we.eq(0)
|
||||
self.comb += [
|
||||
cmd.addr.eq(sink.address),
|
||||
cmd.valid.eq(sink.valid & request_enable),
|
||||
sink.ready.eq(cmd.ready & request_enable),
|
||||
request_issued.eq(cmd.valid & cmd.ready)
|
||||
]
|
||||
|
||||
# FIFO reservation level counter -----------------------------------------------------------
|
||||
# incremented when data is planned to be queued
|
||||
# decremented when data is dequeued
|
||||
data_dequeued = Signal()
|
||||
self.rsv_level = rsv_level = Signal(max=fifo_depth+1)
|
||||
self.sync += [
|
||||
If(request_issued,
|
||||
If(~data_dequeued, rsv_level.eq(self.rsv_level + 1))
|
||||
).Elif(data_dequeued,
|
||||
rsv_level.eq(rsv_level - 1)
|
||||
)
|
||||
]
|
||||
self.comb += request_enable.eq(rsv_level != fifo_depth)
|
||||
|
||||
# FIFO -------------------------------------------------------------------------------------
|
||||
fifo = stream.SyncFIFO([("data", port.data_width)], fifo_depth, fifo_buffered)
|
||||
self.submodules += fifo
|
||||
|
||||
self.comb += [
|
||||
rdata.connect(fifo.sink, omit={"id", "resp"}),
|
||||
fifo.source.connect(source),
|
||||
data_dequeued.eq(source.valid & source.ready)
|
||||
]
|
||||
|
||||
def add_csr(self):
|
||||
self._base = CSRStorage(32)
|
||||
self._length = CSRStorage(32)
|
||||
self._start = CSR()
|
||||
self._done = CSRStatus()
|
||||
self._loop = CSRStorage()
|
||||
|
||||
self._localstart = Signal() # 29.12.20/KQ local starter
|
||||
|
||||
# # #
|
||||
|
||||
shift = log2_int(self.port.data_width//8)
|
||||
base = Signal(self.port.address_width)
|
||||
offset = Signal(self.port.address_width)
|
||||
length = Signal(self.port.address_width)
|
||||
self.comb += [
|
||||
base.eq(self._base.storage[shift:]),
|
||||
length.eq(self._length.storage[shift:]),
|
||||
]
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
fsm.act("IDLE",
|
||||
self._done.status.eq(1),
|
||||
If(self._start.re | self._localstart, # 29.12.20/KQ local starter (#If(self._start.re,)
|
||||
NextValue(offset, 0),
|
||||
NextState("RUN"),
|
||||
)
|
||||
)
|
||||
fsm.act("RUN",
|
||||
self.sink.valid.eq(1),
|
||||
self.sink.address.eq(base + offset),
|
||||
If(self.sink.ready,
|
||||
NextValue(offset, offset + 1),
|
||||
If(offset == (length - 1),
|
||||
If(self._loop.storage,
|
||||
NextValue(offset, 0)
|
||||
).Else(
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# LiteDRAMDMAWriter --------------------------------------------------------------------------------
|
||||
|
||||
class LiteDRAMDMAWriter(Module, AutoCSR):
|
||||
"""Write data to DRAM memory.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
port : port
|
||||
Port on the DRAM memory controller to write to (Native or AXI).
|
||||
|
||||
fifo_depth : int
|
||||
How many requests the input FIFO can contain (and thus how many write
|
||||
requests can be outstanding at once).
|
||||
|
||||
fifo_buffered : bool
|
||||
Implement FIFO in Block Ram.
|
||||
|
||||
Attributes
|
||||
----------
|
||||
sink : Record("address", "data")
|
||||
Sink for DRAM addresses and DRAM data word to be written too.
|
||||
"""
|
||||
def __init__(self, port, fifo_depth=16, fifo_buffered=False):
|
||||
assert isinstance(port, (LiteDRAMNativePort, LiteDRAMAXIPort))
|
||||
self.port = port
|
||||
self.sink = sink = stream.Endpoint([("address", port.address_width),
|
||||
("data", port.data_width)])
|
||||
|
||||
# # #
|
||||
|
||||
# Native / AXI selection -------------------------------------------------------------------
|
||||
is_native = isinstance(port, LiteDRAMNativePort)
|
||||
is_axi = isinstance(port, LiteDRAMAXIPort)
|
||||
if is_native:
|
||||
(cmd, wdata) = port.cmd, port.wdata
|
||||
elif is_axi:
|
||||
(cmd, wdata) = port.aw, port.w
|
||||
else:
|
||||
raise NotImplementedError
|
||||
|
||||
# FIFO -------------------------------------------------------------------------------------
|
||||
fifo = stream.SyncFIFO([("data", port.data_width)], fifo_depth, fifo_buffered)
|
||||
self.submodules += fifo
|
||||
|
||||
if is_native:
|
||||
self.comb += cmd.we.eq(1)
|
||||
self.comb += [
|
||||
cmd.addr.eq(sink.address),
|
||||
cmd.valid.eq(fifo.sink.ready & sink.valid),
|
||||
sink.ready.eq(fifo.sink.ready & cmd.ready),
|
||||
fifo.sink.valid.eq(sink.valid & cmd.ready),
|
||||
fifo.sink.data.eq(sink.data)
|
||||
]
|
||||
|
||||
if is_native:
|
||||
self.comb += wdata.we.eq(2**(port.data_width//8)-1)
|
||||
if is_axi:
|
||||
self.comb += wdata.strb.eq(2**(port.data_width//8)-1)
|
||||
self.comb += [
|
||||
wdata.valid.eq(fifo.source.valid),
|
||||
fifo.source.ready.eq(wdata.ready),
|
||||
wdata.data.eq(fifo.source.data)
|
||||
]
|
||||
|
||||
def add_csr(self):
|
||||
self._sink = self.sink
|
||||
self.sink = stream.Endpoint([("data", self.port.data_width)])
|
||||
|
||||
self._base = CSRStorage(32)
|
||||
self._length = CSRStorage(32)
|
||||
self._start = CSR()
|
||||
self._done = CSRStatus()
|
||||
self._loop = CSRStorage()
|
||||
|
||||
# # #
|
||||
|
||||
shift = log2_int(self.port.data_width//8)
|
||||
base = Signal(self.port.address_width)
|
||||
offset = Signal(self.port.address_width)
|
||||
length = Signal(self.port.address_width)
|
||||
self.comb += [
|
||||
base.eq(self._base.storage[shift:]),
|
||||
length.eq(self._length.storage[shift:]),
|
||||
]
|
||||
|
||||
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
|
||||
fsm.act("IDLE",
|
||||
self._done.status.eq(1),
|
||||
If(self._start.re,
|
||||
NextValue(offset, 0),
|
||||
NextState("RUN"),
|
||||
)
|
||||
)
|
||||
fsm.act("RUN",
|
||||
self._sink.valid.eq(self.sink.valid),
|
||||
self._sink.data.eq(self.sink.data),
|
||||
self._sink.address.eq(base + offset),
|
||||
self.sink.ready.eq(self._sink.ready),
|
||||
If(self.sink.valid & self.sink.ready,
|
||||
NextValue(offset, offset + 1),
|
||||
If(offset == (length - 1),
|
||||
If(self._loop.storage,
|
||||
NextValue(offset, 0)
|
||||
).Else(
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
|
@ -0,0 +1,233 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# dramtransfer.py
|
||||
#
|
||||
# DRAM access
|
||||
#
|
||||
# History:
|
||||
# --------
|
||||
# 21.12.20/KQ Initial test
|
||||
# 30.12.20/KQ Working (renamed) version
|
||||
#
|
||||
|
||||
from migen import *
|
||||
from migen.fhdl.specials import Memory
|
||||
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage, CSRField, CSRAccess
|
||||
from litex.soc.integration.doc import AutoDoc, ModuleDoc
|
||||
|
||||
from litex.soc.interconnect.csr import *
|
||||
#from litedram.common import LiteDRAMNativePort
|
||||
from litedram.core.crossbar import LiteDRAMCrossbar
|
||||
from litedram.frontend import dma
|
||||
|
||||
class DRAMTransfer(Module, AutoCSR, AutoDoc, ModuleDoc):
|
||||
"""
|
||||
DRAMTransfer class provides the protocol logic to access DRAM values via LiteDRAM
|
||||
|
||||
Usage:
|
||||
######
|
||||
|
||||
#. Load ``b32Address`` with base address of range to read from (DRAM: >= 0x40000000)
|
||||
|
||||
#. Indicate length of range to read by setting up ``b8Len`` (not used currently,
|
||||
allways ``maxwords`` * 4 bytes will be loaded (words à 32-bit).
|
||||
|
||||
#. Finally, enable processing by setting ``bEnable`` to true (1).
|
||||
|
||||
#. Once ``bValid`` becomes true (1), FPGA local memory is loaded, deactivate ``bEnable``
|
||||
|
||||
#. To retrieve, load ``b9Offset`` with offset (from base adress) to read from (0 .. 511),
|
||||
``b32Data`` will contain the 32-bit value (from local FPGA memory @offset)
|
||||
|
||||
Inputs:
|
||||
#######
|
||||
|
||||
:b32Address: Base DRAM Address to load from
|
||||
|
||||
:b8Len: Length (0..255) of range to read from (i.e. # of bytes - not used currently - allways reading 32 bytes!)
|
||||
|
||||
:bEnable: To enable running (after initialization)
|
||||
|
||||
:b9Offset: Offset (0..511) into local FPGA memory to read from
|
||||
|
||||
Output:
|
||||
#######
|
||||
|
||||
:bValid: Indicate validity of local FPGA memory, i.e. 'loaded'
|
||||
|
||||
:b32Data: Local FPGA memory at b9Offset
|
||||
|
||||
"""
|
||||
def __init__(self, maxwords=8, dma_reader=None, sync_fifo=None):
|
||||
# Inputs
|
||||
self.b32Address = CSRStorage(32, reset_less=True,
|
||||
fields=[CSRField("Address", size=32, description="*Field*: 32-Bit value")],
|
||||
description="""
|
||||
Base DRAM address, to load from
|
||||
""")
|
||||
self.b8Len = CSRStorage(8, reset_less=True,
|
||||
fields=[CSRField("Len", size=8, description="*Field*: 8-Bit value (0..max)")],
|
||||
description="""
|
||||
Length of range to load, currently not used (allways 4 assumed)
|
||||
""")
|
||||
self.bEnable = CSRStorage(1, reset_less=True,
|
||||
fields=[CSRField("Enable", size=1, description="*Field*: bit", values=[
|
||||
("0", "DISABLED", "Loading enabled"),
|
||||
("1", "ENABLED", "Loading disabled"),
|
||||
])
|
||||
],
|
||||
description="""
|
||||
Enable/disabling DRAM access
|
||||
""")
|
||||
self.b9Offset = CSRStorage(9, reset_less=True,
|
||||
fields=[CSRField("Offset", size=12, description="*Field*: 9-Bit value (0..511)")],
|
||||
description="""
|
||||
Offset added to base address.
|
||||
""")
|
||||
|
||||
# Outputs
|
||||
self.bValid = CSRStorage(1, reset_less=True,
|
||||
fields=[CSRField("Valid", size=1, description="*Field*: bit", values=[
|
||||
("0", "INVALID", "Data output not available"),
|
||||
("1", "VALID", "Data valid"),
|
||||
])
|
||||
],
|
||||
description="""
|
||||
Data valid indication
|
||||
""")
|
||||
self.b32Data = CSRStorage(32, reset_less=True,
|
||||
fields=[CSRField("Data", size=32, description="*Field*: 32-Bit value")],
|
||||
description="""
|
||||
Actual value read
|
||||
""")
|
||||
self.b32RCount = CSRStorage(32, reset_less=True,
|
||||
fields=[CSRField("RCount", size=32, description="*Field*: 32-Bit value")],
|
||||
description="""
|
||||
No. of FIFO entries read so far (only for testing purposes)
|
||||
""")
|
||||
|
||||
# Local 'wire' data
|
||||
self.b32MemPt = Signal(32) # WRITE: Local FPGA memory offset pointer
|
||||
self.b2Address = Signal(3) # READ: Adress conversion helper
|
||||
self.bData = Signal(32) # READ: Helper output data
|
||||
|
||||
storage = Memory(32, maxwords) # Local FPGA memory
|
||||
self.specials += storage
|
||||
|
||||
|
||||
# ---------------------- Local (FPGA) memory DMA filling from DRAM ---------------------------------------------
|
||||
if (dma_reader != None) and (sync_fifo != None):
|
||||
# FPGA local memory write port (driven by FSM, s.b.)
|
||||
wrport = storage.get_port(write_capable=True)
|
||||
self.specials += wrport
|
||||
|
||||
fsm = FSM(reset_state="IDLE") # FSM starts idling ...
|
||||
self.submodules += fsm
|
||||
|
||||
# Prepare DRAM address to load from ...
|
||||
self.sync += dma_reader._base.storage.eq(self.b32Address.storage) # Base DRAM adress to load from
|
||||
self.sync += dma_reader._length.storage.eq(maxwords*4) # Fixed byte length of chunk to load from DRAM
|
||||
|
||||
fsm.act("IDLE",
|
||||
If(self.bEnable.storage & ~self.bValid.storage, # Enabled & not busy already
|
||||
NextValue(dma_reader._localstart, 1), # FPGA DMA self starter (special in litedram/frontend/dma.py)
|
||||
NextValue(self.b32MemPt, 0), # Reset queue offset (counter)
|
||||
NextState("DMAWAIT")
|
||||
).Elif(~self.bEnable.storage, # Reset from external world first
|
||||
NextValue(self.bValid.storage, 0) # to reset ... before possible re-enable
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("DMAWAIT",
|
||||
NextValue(dma_reader._localstart, 0), # Reset FPGA DMA self starter
|
||||
NextValue(self.bValid.storage, dma_reader._done.status), # Indicate DMA transfer finished to external ...
|
||||
If(dma_reader._done.status, # Wait 'til DMA transfer finishes ...
|
||||
NextState("FIFOREAD")
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("FIFOREAD",
|
||||
If(sync_fifo.source.valid, # fifo.readable, # Data in queue waiting?
|
||||
NextValue(self.b32RCount.storage, self.b32RCount.storage + 1), # Increment
|
||||
If(self.b32MemPt < maxwords, # Legal address?
|
||||
NextValue(wrport.adr, self.b32MemPt), # Local offset into memory
|
||||
NextValue(wrport.dat_w, sync_fifo.source.payload.data), # Store current value -> memory
|
||||
NextValue(wrport.we, 1) # Write enable
|
||||
),
|
||||
NextValue(sync_fifo.source.ready, 1), # fifo.re, 1), # ACK readable, request next FIFO entry
|
||||
NextState("TESTFIFO")
|
||||
)
|
||||
)
|
||||
|
||||
fsm.act("TESTFIFO",
|
||||
NextValue(wrport.we, 0), # Stop transfer to memory
|
||||
If(self.b32MemPt >= (maxwords-1),
|
||||
NextValue(self.b32MemPt, 0), # Reset counter
|
||||
NextValue(self.bValid.storage, 1), # Indicate validity of results
|
||||
NextState("IDLE")
|
||||
).Else(
|
||||
NextValue(self.b32MemPt, self.b32MemPt + 1), # Increment
|
||||
NextState("FIFOREAD")
|
||||
),
|
||||
NextValue(sync_fifo.source.ready, 0) #fifo.re, 0), # Reset ACK
|
||||
)
|
||||
|
||||
|
||||
# --------------------------- Local (FPGA) memory retrieval access -----------------------------------------------
|
||||
# FPGA local memory read port
|
||||
rdport = storage.get_port()
|
||||
self.specials += rdport
|
||||
self.comb += [ # Read from (FPGA local) memory
|
||||
self.b2Address.eq(self.b9Offset.storage[0:2]), # Filter bits 0..1 (range 0-3)
|
||||
If(self.b9Offset.storage < maxwords,
|
||||
#rdport.adr.eq(self.b9Offset.storage), # w/ translation!
|
||||
If(self.b2Address == 0,
|
||||
rdport.adr.eq(self.b9Offset.storage | 3) # 0->3
|
||||
).Elif(self.b2Address == 1,
|
||||
rdport.adr.eq((self.b9Offset.storage & 0x1FC) | 2) # 1->2
|
||||
).Elif(self.b2Address == 2,
|
||||
rdport.adr.eq((self.b9Offset.storage & 0x1FC) | 1) # 2->1
|
||||
).Elif(self.b2Address == 3,
|
||||
rdport.adr.eq(self.b9Offset.storage & 0x1FC) # 3->0
|
||||
),
|
||||
self.bData.eq(rdport.dat_r) # Assign to external var. ...
|
||||
),
|
||||
]
|
||||
self.sync += self.b32Data.storage.eq(self.bData) # Assign to external var. ...
|
||||
|
||||
|
||||
def DRAMTransfer_testbench(DRAMTransfer):
|
||||
print("----- DRAM testbench -----")
|
||||
yield DRAMTransfer.bEnable.storage.eq(False)
|
||||
yield
|
||||
yield DRAMTransfer.b32Address.storage.eq(0x40190000)
|
||||
yield
|
||||
iOffset = 0
|
||||
yield DRAMTransfer.b9Offset.storage.eq(iOffset)
|
||||
yield
|
||||
yield DRAMTransfer.b8Len.storage.eq(4)
|
||||
yield
|
||||
yield DRAMTransfer.bEnable.storage.eq(True)
|
||||
yield
|
||||
#
|
||||
for i in range(32): # Send the whole data & restart ...
|
||||
print(i, ": ", sep="", end="")
|
||||
|
||||
bValid = (yield DRAMTransfer.bValid.storage)
|
||||
if bValid == True:
|
||||
print(hex((yield DRAMTransfer.b32Data.storage))) # Actual pin to move
|
||||
yield DRAMTransfer.bEnable.storage.eq(False) # Reset request
|
||||
else:
|
||||
if (yield DRAMTransfer.bEnable.storage) == False:
|
||||
print("New request")
|
||||
iOffset = iOffset + 4
|
||||
yield DRAMTransfer.b9Offset.storage.eq(iOffset)
|
||||
yield DRAMTransfer.bEnable.storage.eq(True)
|
||||
else:
|
||||
print("-- invalid --")
|
||||
yield
|
||||
|
||||
if __name__ == "__main__":
|
||||
DRAMTransfer = DRAMTransfer(maxwords=8, sync_fifo=None)
|
||||
run_simulation(DRAMTransfer, DRAMTransfer_testbench(DRAMTransfer), vcd_name="dramtransfer.vcd", clocks={"sys":16})
|
|
@ -0,0 +1,61 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
#
|
||||
# systime.py
|
||||
#
|
||||
# Clock (simulation)
|
||||
#
|
||||
# History:
|
||||
# --------
|
||||
# 31.12.20/KQ Initial version
|
||||
#
|
||||
|
||||
from migen import *
|
||||
from migen.fhdl.specials import Memory
|
||||
from litex.soc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage, CSRField, CSRAccess
|
||||
from litex.soc.integration.doc import AutoDoc, ModuleDoc
|
||||
|
||||
class SysTime(Module, AutoCSR, AutoDoc, ModuleDoc):
|
||||
"""
|
||||
SysTime class provides the missing system time
|
||||
|
||||
Usage:
|
||||
######
|
||||
|
||||
#. Adjust clock by providing current Time to ``b32CurrentMSeconds``
|
||||
|
||||
#. Current Time may be read via ``b32CurrentMSeconds``
|
||||
|
||||
Inputs:
|
||||
#######
|
||||
|
||||
:b32CurrentMSeconds: Current milliseconds within day to set
|
||||
|
||||
Output:
|
||||
#######
|
||||
|
||||
:b32CurrentMSeconds: Current milliseconds within day since 00:00:00
|
||||
|
||||
"""
|
||||
def __init__(self, comparecount=0x0000EA90):
|
||||
# Input/Output
|
||||
self.b32CurrentMSeconds = CSRStorage(32, reset_less=True,
|
||||
fields=[CSRField("CurrentMSeconds", size=32, description="*Field*: 32-Bit value")],
|
||||
description="""
|
||||
Current milliseconds within day since 00:00:00.000
|
||||
""")
|
||||
|
||||
# Local (internal)
|
||||
self.b32Counter = Signal(32) # System frequency runner
|
||||
|
||||
# Simple time count function
|
||||
self.sync += [
|
||||
self.b32Counter.eq(self.b32Counter + 1), # Run system frequency counter
|
||||
If(self.b32Counter == comparecount, # Approx. 1ms
|
||||
self.b32Counter.eq(0),
|
||||
self.b32CurrentMSeconds.storage.eq(self.b32CurrentMSeconds.storage + 1),
|
||||
If(self.b32CurrentMSeconds.storage > 86399999, # Daily max. reached?
|
||||
self.b32CurrentMSeconds.storage.eq(0) # Then: reset
|
||||
)
|
||||
)
|
||||
]
|
|
@ -18,6 +18,7 @@
|
|||
# 19.09.20/KQ Project renamed 'NeoPixelar' (swedish plural for NeoPixel ...)
|
||||
# 20.11.20/KQ Input provided: U28 -> J1 (1, 2, 3, [4=GND], 5, 6, 7), J2 (1, 2, [4=GND])
|
||||
# (U15 -> J7 ([4=GND], 5, 7), J8 (1, 2, 3, [4=GND], 5, 6, 7))
|
||||
# 02.01.21/KQ DMA DRAM access integration started
|
||||
#
|
||||
# Build/Use ----------------------------------------------------------------------------------------
|
||||
# - 'python3 neopixelar.py --build --revision=7.0 --uart-name=crossover --with-etherbone --ip-address=192.168.1.20 --csr-csv=build/csr.csv'
|
||||
|
@ -65,6 +66,10 @@ from litex.build.generic_platform import *
|
|||
|
||||
import litex.soc.doc as lxsocdoc
|
||||
|
||||
# KQ's helper modules ...
|
||||
from modules.systime import SysTime
|
||||
from modules.dramtransfer import DRAMTransfer
|
||||
|
||||
from neopixelengine import NeoPixelEngine
|
||||
|
||||
from helpers.prepare_firmware import copyjob
|
||||
|
@ -335,8 +340,7 @@ class BaseSoC(SoCCore):
|
|||
# Add platform specific I/O
|
||||
platform.add_extension(_gpios) # General LED outputs
|
||||
|
||||
# OR values for LED signalling test
|
||||
# For U28
|
||||
# For U28 3.3V(!) inputs: (also see separate picture)
|
||||
self.J1_1 = J1_1 = platform.request("gpio", 0) # Pins for logical evaluation
|
||||
self.J1_2 = J1_2 = platform.request("gpio", 1)
|
||||
self.J1_3 = J1_3 = platform.request("gpio", 2)
|
||||
|
@ -346,23 +350,7 @@ class BaseSoC(SoCCore):
|
|||
self.J2_1 = J2_1 = platform.request("gpio", 14)
|
||||
self.J2_2 = J2_2 = platform.request("gpio", 15)
|
||||
'''
|
||||
J1_1 = Signal(1)
|
||||
self.comb += J1_1.eq(platform.request("gpio", 0)) # Input data pins
|
||||
J1_2 = Signal(1)
|
||||
self.comb += J1_2.eq(platform.request("gpio", 1))
|
||||
J1_3 = Signal(1)
|
||||
self.comb += J1_3.eq(platform.request("gpio", 2))
|
||||
J1_5 = Signal(1)
|
||||
self.comb += J1_5.eq(platform.request("gpio", 3))
|
||||
J1_6 = Signal(1)
|
||||
self.comb += J1_6.eq(platform.request("gpio", 4))
|
||||
J1_7 = Signal(1)
|
||||
self.comb += J1_7.eq(platform.request("gpio", 5))
|
||||
J2_1 = Signal(1)
|
||||
self.comb += J2_1.eq(platform.request("gpio", 14))
|
||||
J2_2 = Signal(1)
|
||||
self.comb += J2_2.eq(platform.request("gpio", 15))
|
||||
# For U15
|
||||
# For U15 (not used currently)
|
||||
J7_5 = Signal(1)
|
||||
self.comb += J7_5.eq(platform.request("gpio", 87))
|
||||
J7_7 = Signal(1)
|
||||
|
@ -380,10 +368,10 @@ class BaseSoC(SoCCore):
|
|||
J8_7 = Signal(1)
|
||||
self.comb += J8_7.eq(platform.request("gpio", 103))
|
||||
'''
|
||||
# OR it all together
|
||||
# OR it all together: Every input lights LED ...
|
||||
self.led_logic1 = led_logic1 = Signal(1)
|
||||
self.comb += led_logic1.eq(J1_1 | J1_2 | J1_3 | J1_5 | J1_6 | J1_7 | J2_1 | J2_2)
|
||||
#led_logic2 = Signal(1)
|
||||
#led_logic2 = Signal(1) # Not used currently
|
||||
#self.comb += led_logic2.eq(J8_1 | J8_2 | J8_3 | J8_5 | J8_6 | J8_7 | J7_5 | J7_7)
|
||||
|
||||
# Base counter (used for clocking)
|
||||
|
@ -393,8 +381,12 @@ class BaseSoC(SoCCore):
|
|||
# USERLED blink (on-board LED)
|
||||
# only w/ uart-name=crossover option:
|
||||
if kwargs["uart_name"] not in ["serial", "bridge"]:
|
||||
self.comb += platform.request("user_led_n").eq(~(counter[23] | led_logic1)) #| led_logic2) # ~2Hz
|
||||
self.comb += platform.request("user_led_n").eq(~(counter[23] | led_logic1)) #| led_logic2) # ~2Hz | inputs
|
||||
|
||||
# System time (count)
|
||||
self.submodules.systime = systime = SysTime(comparecount=0x0000EA90)
|
||||
self.add_csr("systime")
|
||||
|
||||
# Adjust no. for your actual project ...
|
||||
max_TABLES = 3 # 1..16
|
||||
max_LEDS_per_chain = 27 # 1..256
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
#ifndef DRAMTRANSFER_H
|
||||
#define DRAMTRANSFER_H
|
||||
|
||||
//
|
||||
// dramtransfer.h
|
||||
//
|
||||
// History:
|
||||
// --------
|
||||
// 29.12.20/KQ Initial version
|
||||
//
|
||||
|
||||
#define FIFOSIZE 256 //128, 8
|
||||
#define TIMEOUT 100
|
||||
extern int load_FPGA(uint32_t iBaseAddress, int8_t bLen);
|
||||
extern int32_t retrieve_FPGA(int iOffset);
|
||||
extern void dramtest(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef SYSTIME_H
|
||||
#define SYSTIME_H
|
||||
|
||||
//
|
||||
// systime.h
|
||||
//
|
||||
// History:
|
||||
// --------
|
||||
// 31.12.20/KQ Initial version
|
||||
//
|
||||
|
||||
extern uint32_t systime(uint32_t setval);
|
||||
extern void setsystime(int hh, int mm, int ss);
|
||||
extern void getsystime(int *hh, int *mm, int *ss);
|
||||
|
||||
#endif
|
|
@ -1,9 +1,12 @@
|
|||
INCLUDE linker/output_format.ld
|
||||
/* ENTRY(_start) */
|
||||
ENTRY(illumination)
|
||||
ENTRY(_start)
|
||||
|
||||
INCLUDE ../build/colorlight_5a_75b/software/include/generated/regions.ld
|
||||
|
||||
MEMORY {
|
||||
main_sram : ORIGIN = 0x403FC000, LENGTH = 0x00002000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
|
@ -55,7 +58,8 @@ SECTIONS
|
|||
FILL(0);
|
||||
. = ALIGN(8);
|
||||
_edata = .;
|
||||
} > sram AT > main_ram
|
||||
/* sram -> main_sram (DRAM) */
|
||||
} > main_sram AT > main_ram
|
||||
|
||||
.bss :
|
||||
{
|
||||
|
@ -70,7 +74,8 @@ SECTIONS
|
|||
. = ALIGN(8);
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > sram AT > main_ram
|
||||
/* sram -> main_sram (DRAM) */
|
||||
} > main_sram AT > main_ram
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
|
@ -79,7 +84,8 @@ SECTIONS
|
|||
}
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 8);
|
||||
/* STACK: sram -> main_sram (DRAM) */
|
||||
PROVIDE(_fstack = ORIGIN(main_sram) + LENGTH(main_sram) - 8);
|
||||
|
||||
PROVIDE(_fdata_rom = LOADADDR(.data));
|
||||
PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
INCLUDE linker/output_format.ld
|
||||
/* ENTRY(_start) */
|
||||
ENTRY(illumination)
|
||||
ENTRY(_start)
|
||||
|
||||
INCLUDE ../build/colorlight_5a_75b/software/include/generated/regions.ld
|
||||
|
||||
MEMORY {
|
||||
main_ram2 : ORIGIN = 0x40200000, LENGTH = 0x00200000
|
||||
main_sram : ORIGIN = 0x403FC000, LENGTH = 0x00002000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
@ -59,7 +59,7 @@ SECTIONS
|
|||
FILL(0);
|
||||
. = ALIGN(8);
|
||||
_edata = .;
|
||||
} > sram AT > main_ram2
|
||||
} > main_sram AT > main_ram2
|
||||
|
||||
.bss :
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ SECTIONS
|
|||
. = ALIGN(8);
|
||||
_ebss = .;
|
||||
_end = .;
|
||||
} > sram AT > main_ram2
|
||||
} > main_sram AT > main_ram2
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
|
@ -83,7 +83,8 @@ SECTIONS
|
|||
}
|
||||
}
|
||||
|
||||
PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 8);
|
||||
/* STACK: sram -> main_sram (DRAM) */
|
||||
PROVIDE(_fstack = ORIGIN(main_sram) + LENGTH(main_sram) - 8);
|
||||
|
||||
PROVIDE(_fdata_rom = LOADADDR(.data));
|
||||
PROVIDE(_edata_rom = LOADADDR(.data) + SIZEOF(.data));
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# ramcreate.sh
|
||||
# A rather obbscure RAM s/w builder (needs transformation to actual makefile setup ;)
|
||||
# A rather obscure RAM s/w builder (needs transformation to actual makefile setup ;)
|
||||
#
|
||||
# History:
|
||||
# --------
|
||||
# 10.10.20/KQ Initial (running) version
|
||||
#
|
||||
PROJECTNAME="neopixelar" # Adjust w/ local path
|
||||
|
||||
# Test for missing ('zero length') basefilenames
|
||||
if [ -z $1 ] || [ -z $2 ] || [ -z $3 ]; then
|
||||
|
@ -14,6 +15,15 @@ if [ -z $1 ] || [ -z $2 ] || [ -z $3 ]; then
|
|||
echo "example: ./ramcreate.sh main illumination 1 (for RAM bank #1)"
|
||||
exit
|
||||
fi
|
||||
echo "Creating $PROJECTNAME application ..."
|
||||
|
||||
# Additional user libs, not project specific
|
||||
LIBSYSTIME="systime"
|
||||
LIBPRINTF="my_vsnprintf"
|
||||
|
||||
# Additional user libs, not project specific
|
||||
LIBSYSTIME="systime"
|
||||
LIBPRINTF="my_vsnprintf"
|
||||
|
||||
# Adjust these paths according to your local installation !!!
|
||||
MY_LOCAL_LITEX_PATH=$HOME"/fpga/litex"
|
||||
|
@ -33,7 +43,7 @@ CPU_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/cores/cpu/vexriscv"
|
|||
COMPILER_RT_DIRECTORY="$MY_LOCAL_LITEX_PATH/pythondata-software-compiler_rt/pythondata_software_compiler_rt/data"
|
||||
SOC_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc"
|
||||
#export BUILDINC_DIRECTORY
|
||||
BUILDINC_DIRECTORY="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/neopixelar/build/colorlight_5a_75b/software/include"
|
||||
BUILDINC_DIRECTORY="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/$PROJECTNAME/build/colorlight_5a_75b/software/include"
|
||||
LIBCOMPILER_RT_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/libcompiler_rt"
|
||||
LIBBASE_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/libbase"
|
||||
LIBLITEDRAM_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitedram"
|
||||
|
@ -42,7 +52,7 @@ LIBLITESPI_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitespi"
|
|||
LIBLITESDCARD_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/liblitesdcard"
|
||||
BIOS_DIRECTORY="$MY_LOCAL_LITEX_PATH/litex/litex/soc/software/bios"
|
||||
|
||||
BIOSPATH="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/neopixelar/build/colorlight_5a_75b/software/bios"
|
||||
BIOSPATH="/mnt/a30054ad-3fe6-444a-8d93-16df937e448e/projects/fpga/$PROJECTNAME/build/colorlight_5a_75b/software/bios"
|
||||
OBJECTS="$BIOSPATH/isr.o $BIOSPATH/boot-helper.o $BIOSPATH/boot.o $BIOSPATH/helpers.o $BIOSPATH/cmd_bios.o $BIOSPATH/cmd_mem.o $BIOSPATH/cmd_boot.o $BIOSPATH/cmd_i2c.o $BIOSPATH/cmd_spiflash.o $BIOSPATH/cmd_litedram.o $BIOSPATH/cmd_liteeth.o $BIOSPATH/cmd_litesdcard.o $BIOSPATH/complete.o $BIOSPATH/readline.o"
|
||||
|
||||
LXP="../build/colorlight_5a_75b/software"
|
||||
|
@ -69,15 +79,21 @@ then
|
|||
echo "*** gcc for $1.c failed!"
|
||||
exit $?
|
||||
fi
|
||||
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/my_vsnprintf.c -o build/my_vsnprintf.o
|
||||
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/$LIBPRINTF.c -o build/$LIBPRINTF.o
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo "*** gcc for my_vsnprintf.c failed!"
|
||||
echo "*** gcc for $LIBPRINTF.c failed!"
|
||||
exit $?
|
||||
fi
|
||||
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-gcc -c $COMMONFLAGS $CFLAGS -Wa,-fPIC source/$LIBSYSTIME.c -o build/$LIBSYSTIME.o
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo "*** gcc for $LIBSYSTIME.c failed!"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
echo "Linking ..."
|
||||
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o build/my_vsnprintf.o lib/rv32ilibm.a lib/rv32ilibgcc.a -o build/$1.elf
|
||||
$MY_LOCAL_LITEX_PATH/riscv64-unknown-elf-gcc-8.3.0-2019.08.0-x86_64-linux-ubuntu14/bin/riscv64-unknown-elf-ld $LDFLAGS -T linker/ram$3.ld -N $CRT0 $OBJECTS $LXR build/$2.o build/$1.o build/$LIBSYSTIME.o build/$LIBPRINTF.o lib/rv32ilibm.a lib/rv32ilibgcc.a -o build/$1.elf
|
||||
if [ $? -ne 0 ];
|
||||
then
|
||||
echo "*** Link/Loader for build/$1.elf failed!"
|
||||
|
@ -115,3 +131,4 @@ fi
|
|||
# screen /dev/ttyUSB0 115200
|
||||
# Press 'Ctrl-A k' to terminate ...
|
||||
echo "Done (don't worry about the download 'error' in red!)."
|
||||
echo "Loaded project $PROJECTNAME to RAM bank #$3 <---"
|
||||
|
|
|
@ -3,4 +3,5 @@ illumination.c - This is a sample application, demonstrating the use
|
|||
of the 'neopixelengine' (the documentation can be found
|
||||
under ./build/documentation/http/index.html)
|
||||
my_vsnprintf.c - Some helpers. For float formatting use printf1() (really ugly!)
|
||||
|
||||
dramtransfer.c - DMA DRAM access loader
|
||||
systime.c - (Daily) Time helper
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
//
|
||||
// dramtransfer.c
|
||||
// DRAM transfer routines
|
||||
//
|
||||
// History:
|
||||
// --------
|
||||
// 21.12.20/KQ Initial version
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
#include <string.h>
|
||||
#include <uart.h>
|
||||
#include <system.h>
|
||||
#include <id.h>
|
||||
#include <irq.h>
|
||||
#include <crc.h>
|
||||
#include "boot.h"
|
||||
#include "readline.h"
|
||||
#include "helpers.h"
|
||||
#include "command.h"
|
||||
|
||||
#include "../../build/colorlight_5a_75b/software/include/generated/csr.h"
|
||||
#include "../../build/colorlight_5a_75b/software/include/generated/soc.h"
|
||||
#include "../../build/colorlight_5a_75b/software/include/generated/mem.h"
|
||||
#include "../../build/colorlight_5a_75b/software/include/generated/git.h"
|
||||
|
||||
#include <spiflash.h>
|
||||
|
||||
#include <liblitedram/sdram.h>
|
||||
|
||||
#include <libliteeth/udp.h>
|
||||
#include <libliteeth/mdio.h>
|
||||
|
||||
#include <liblitespi/spiflash.h>
|
||||
|
||||
#include <liblitesdcard/sdcard.h>
|
||||
|
||||
#include "../include/systime.h"
|
||||
#include "../include/dramtransfer.h"
|
||||
|
||||
extern void busy_wait(unsigned int ms); // Worx!
|
||||
|
||||
// Load FPGA from DRAM
|
||||
int load_FPGA(uint32_t iBaseAddress, int8_t bLen)
|
||||
{
|
||||
int i;
|
||||
|
||||
flush_l2_cache(); // Strictly nec. for longer transfers
|
||||
|
||||
if((iBaseAddress & 0xF) != 0) {
|
||||
iBaseAddress &= 0xFFFFFFF0; // Enforce 16-byte alignment
|
||||
printf("*** load_FPGA(): iBaseAddress alignment needs to be 16 Byte! Using %08Xh\n", iBaseAddress);
|
||||
}
|
||||
if((iBaseAddress < 0x40000000) || (iBaseAddress > 0x40400000)) {
|
||||
printf("*** load_FPGA(): iBaseAddress not within DRAM range!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
dramtransfer_bEnable_write(0); // For address change, turn off first!
|
||||
dramtransfer_b32Address_write(iBaseAddress); // Provide a valid DRAM address
|
||||
dramtransfer_bEnable_write(1); // Start DMA pickup & FIFO fill ...
|
||||
for(i = 0; i < TIMEOUT; i++) {
|
||||
if(dramtransfer_bValid_read()) // Wait 'til transfer done
|
||||
break;
|
||||
}
|
||||
dramtransfer_bEnable_write(0); // Indicate termination of action
|
||||
if(i>=TIMEOUT) { // Timing?
|
||||
printf("*** TIMEOUT: bValid not set?\n");
|
||||
return 0;
|
||||
}
|
||||
return 1; // Ok, FPGA loaded!
|
||||
}
|
||||
|
||||
// Retrieve FPGA memory@offset
|
||||
int32_t retrieve_FPGA(int iOffset)
|
||||
{
|
||||
if((iOffset < 0) || (iOffset >= FIFOSIZE)) {
|
||||
printf("*** retrieve_FPGA(): Invalid offset?!\n");
|
||||
iOffset = 0;
|
||||
}
|
||||
dramtransfer_b9Offset_write(iOffset); // ->memory[offset]
|
||||
return dramtransfer_b32Data_read(); // memory[offset]
|
||||
}
|
||||
|
||||
#define BASEADDRESS 0x40190000
|
||||
#define MAXLOOPS 64 // 8x 0x400 (8x 256 * 4 = 8x 1024) => 0x2000
|
||||
|
||||
void dramtest(void)
|
||||
{
|
||||
uint32_t *TxPtr;
|
||||
int i, j;
|
||||
uint32_t iStart;
|
||||
|
||||
printf("---- DRAM transfer test ----\n");
|
||||
iStart = systime(1); // Reset to defined value ...
|
||||
int iSum = 0; // Time aggregate
|
||||
for(j = 0; j < MAXLOOPS; j++) {
|
||||
// Attention: int32_t Assignments require at least 4 bytes boundary alignment!
|
||||
TxPtr = (uint32_t *)((BASEADDRESS & 0xFFFFFFFC) + j * (FIFOSIZE * sizeof(int32_t)));
|
||||
for(i = 0; i < FIFOSIZE; i++) { // Fill source range data within DRAM
|
||||
*(uint32_t *)(TxPtr+i) = j*FIFOSIZE + i+1;
|
||||
}
|
||||
iStart = systime(0); // Expect 0.70 ms/transfer ...
|
||||
if(load_FPGA((uint32_t)TxPtr, 0)) { // Load <n> bytes from 0x40190000 ... (16 byte aligned!)
|
||||
iSum += (systime(0) - iStart); // Time delta added
|
||||
for(i=0;i<FIFOSIZE;i++) {
|
||||
if((j*FIFOSIZE + i + 1) != retrieve_FPGA(i)) {
|
||||
printf("%d: TxPtr -> %08X (%d 32-bit words) (Count before: %d) ", j, (uint32_t)TxPtr, FIFOSIZE, dramtransfer_b32RCount_read());
|
||||
printf("\n*** FAIL mem[%03d] %d != %08Xh\n", i, j * FIFOSIZE + i + 1, retrieve_FPGA(i));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("*** load_FPGA(): FAILED?!\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(j >= MAXLOOPS) {
|
||||
printf("PASS: %d bytes transferred in %dms w/ %d chuncks of %d bytes/each (0.%d ms/transfer), range %08Xh-%08Xh.\n",
|
||||
MAXLOOPS * 4 * FIFOSIZE, iSum, MAXLOOPS, 4 * FIFOSIZE, iSum*100/MAXLOOPS, BASEADDRESS, BASEADDRESS+MAXLOOPS*4*FIFOSIZE-1);
|
||||
}
|
||||
|
||||
#ifdef XXX
|
||||
printf("\n---- System time test ----\n");
|
||||
systime(86399999-1000);
|
||||
printf("Pre: %d\n", systime(0));
|
||||
busy_wait(2000);
|
||||
printf("Post: %d\n", systime(0));
|
||||
|
||||
int hh, mm, ss; // ------------------ Time adjust test ----------------------
|
||||
setsystime(13,55,0);
|
||||
getsystime(&hh, &mm, &ss);
|
||||
printf("Time now: %02d:%02d:%02d\nWait 60s, press [x] to terminate ...\n", hh, mm, ss);
|
||||
while(!key_eval()) {
|
||||
busy_wait(60000); // 60s
|
||||
getsystime(&hh, &mm, &ss);
|
||||
printf("Time now: %02d:%02d:%02d\nWait 60s, press [x] to terminate ...\n", hh, mm, ss);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,11 +1,12 @@
|
|||
//
|
||||
// ramtest.c
|
||||
// main.c
|
||||
// RAM loadable (& executable!) object
|
||||
//
|
||||
// History:
|
||||
// --------
|
||||
// 07.10.20/KQ Initial version
|
||||
// 18.10.20/KQ RAM version w/ command interpreter loop ready
|
||||
// 02.01.21/KQ DRAM DMA access integrated
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -40,6 +41,7 @@
|
|||
|
||||
#include <liblitesdcard/sdcard.h>
|
||||
|
||||
#include "../include/systime.h"
|
||||
#include "../include/illumination.h"
|
||||
|
||||
extern void busy_wait(unsigned int ms); // Worx!
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
//
|
||||
// systime.c
|
||||
// Little daily time helper routines
|
||||
//
|
||||
// History:
|
||||
// --------
|
||||
// 31.12.20/KQ Initial version
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <console.h>
|
||||
#include <string.h>
|
||||
#include <uart.h>
|
||||
#include <system.h>
|
||||
#include <id.h>
|
||||
#include <irq.h>
|
||||
#include <crc.h>
|
||||
|
||||
#include "../include/systime.h"
|
||||
|
||||
uint32_t systime(uint32_t setval)
|
||||
{
|
||||
if(setval != 0) // Read value?
|
||||
systime_b32CurrentMSeconds_write(setval); // Nope!
|
||||
else // Yap!
|
||||
return systime_b32CurrentMSeconds_read();
|
||||
return setval;
|
||||
}
|
||||
|
||||
void setsystime(int hh, int mm, int ss)
|
||||
{
|
||||
systime((uint32_t)(hh * 3600 + mm * 60 + ss) * 1000);
|
||||
}
|
||||
|
||||
void getsystime(int *hh, int *mm, int *ss)
|
||||
{
|
||||
uint32_t tVal = systime(0)/1000; // ms -> s
|
||||
|
||||
//
|
||||
*hh = tVal / 3600;
|
||||
tVal -= (*hh * 3600);
|
||||
*mm = tVal/60;
|
||||
tVal -= (*mm * 60);
|
||||
*ss = tVal;
|
||||
}
|
||||
|
Loading…
Reference in New Issue