micropython control of SPI works (as far as I can tell)
This commit is contained in:
parent
df9a7dcd8d
commit
3fac5747cc
|
@ -49,7 +49,12 @@ class Waveform(LiteXModule):
|
||||||
origin= 0x18,
|
origin= 0x18,
|
||||||
bitwidth= 16,
|
bitwidth= 16,
|
||||||
rw= True,
|
rw= True,
|
||||||
)
|
),
|
||||||
|
"force_stop" : Register (
|
||||||
|
origin=0x1C,
|
||||||
|
bitwidth=1,
|
||||||
|
rw=True,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
width = 0x20
|
width = 0x20
|
||||||
|
@ -85,6 +90,7 @@ class Waveform(LiteXModule):
|
||||||
wform_size = Signal(counter_max_wid)
|
wform_size = Signal(counter_max_wid)
|
||||||
timer = Signal(timer_wid)
|
timer = Signal(timer_wid)
|
||||||
timer_spacing = Signal(timer_wid)
|
timer_spacing = Signal(timer_wid)
|
||||||
|
force_stop = Signal()
|
||||||
|
|
||||||
self.sync += If(b.cyc & b.stb & ~b.ack,
|
self.sync += If(b.cyc & b.stb & ~b.ack,
|
||||||
Case(b.adr, {
|
Case(b.adr, {
|
||||||
|
@ -118,6 +124,11 @@ class Waveform(LiteXModule):
|
||||||
).Else(
|
).Else(
|
||||||
b.dat_r[0:timer_wid].eq(timer_spacing),
|
b.dat_r[0:timer_wid].eq(timer_spacing),
|
||||||
),
|
),
|
||||||
|
0x1C: If(b.we,
|
||||||
|
force_stop.eq(b.dat_w[0]),
|
||||||
|
).Else(
|
||||||
|
b.dat_r[0].eq(force_stop),
|
||||||
|
),
|
||||||
# (W)A(V)EFO(RM)
|
# (W)A(V)EFO(RM)
|
||||||
"default": b.dat_r.eq(0xAEF0AEF0),
|
"default": b.dat_r.eq(0xAEF0AEF0),
|
||||||
}
|
}
|
||||||
|
@ -136,6 +147,7 @@ class Waveform(LiteXModule):
|
||||||
i_clk = ClockSignal(),
|
i_clk = ClockSignal(),
|
||||||
|
|
||||||
i_run = run,
|
i_run = run,
|
||||||
|
i_force_stop = force_stop,
|
||||||
o_cntr = cntr,
|
o_cntr = cntr,
|
||||||
i_do_loop = do_loop,
|
i_do_loop = do_loop,
|
||||||
o_finished = finished,
|
o_finished = finished,
|
||||||
|
@ -190,11 +202,11 @@ class SPIMaster(Module):
|
||||||
width = 0x20
|
width = 0x20
|
||||||
|
|
||||||
public_registers = {
|
public_registers = {
|
||||||
# The first bit is the "finished" bit, when the master is
|
# The first bit is the "ready" bit, when the master is
|
||||||
# armed and finished with a transmission.
|
|
||||||
# The second bit is the "ready" bit, when the master is
|
|
||||||
# not armed and ready to be armed.
|
# not armed and ready to be armed.
|
||||||
"ready_or_finished": Register(
|
# The second bit is the "finished" bit, when the master is
|
||||||
|
# armed and finished with a transmission.
|
||||||
|
"finished_or_ready": Register(
|
||||||
origin= 0,
|
origin= 0,
|
||||||
bitwidth= 2,
|
bitwidth= 2,
|
||||||
rw=False,
|
rw=False,
|
||||||
|
@ -224,7 +236,7 @@ class SPIMaster(Module):
|
||||||
|
|
||||||
# Same as ready_or_finished, but halts until ready or finished
|
# Same as ready_or_finished, but halts until ready or finished
|
||||||
# goes high. Dangerous, might cause cores to hang!
|
# goes high. Dangerous, might cause cores to hang!
|
||||||
"wait_ready_or_finished": Register(
|
"wait_finished_or_ready": Register(
|
||||||
origin=0x10,
|
origin=0x10,
|
||||||
bitwidth=2,
|
bitwidth=2,
|
||||||
rw= False,
|
rw= False,
|
||||||
|
@ -333,7 +345,8 @@ class SPIMaster(Module):
|
||||||
p_PHASE = phase,
|
p_PHASE = phase,
|
||||||
|
|
||||||
i_clk = ClockSignal(),
|
i_clk = ClockSignal(),
|
||||||
i_rst_L = rst,
|
# module_reset is active high
|
||||||
|
i_rst_L = ~rst,
|
||||||
i_miso = miso,
|
i_miso = miso,
|
||||||
o_mosi = mosi,
|
o_mosi = mosi,
|
||||||
o_sck_wire = sck,
|
o_sck_wire = sck,
|
||||||
|
|
|
@ -15,6 +15,7 @@ module waveform #(
|
||||||
|
|
||||||
/* Waveform output control */
|
/* Waveform output control */
|
||||||
input run,
|
input run,
|
||||||
|
input force_stop,
|
||||||
output reg[COUNTER_MAX_WID-1:0] cntr,
|
output reg[COUNTER_MAX_WID-1:0] cntr,
|
||||||
input do_loop,
|
input do_loop,
|
||||||
output reg finished,
|
output reg finished,
|
||||||
|
@ -57,7 +58,9 @@ localparam WAIT_PERIOD = 13;
|
||||||
|
|
||||||
reg [4-1:0] state = CHECK_START;
|
reg [4-1:0] state = CHECK_START;
|
||||||
|
|
||||||
always @ (posedge clk) case (state)
|
always @ (posedge clk) if (force_stop) begin
|
||||||
|
state <= CHECK_START;
|
||||||
|
end else case (state)
|
||||||
CHECK_START: if (run) begin
|
CHECK_START: if (run) begin
|
||||||
cntr <= 0;
|
cntr <= 0;
|
||||||
ready <= 0;
|
ready <= 0;
|
||||||
|
|
|
@ -15,6 +15,7 @@ module waveform_sim #(
|
||||||
|
|
||||||
/* Waveform output control */
|
/* Waveform output control */
|
||||||
input run,
|
input run,
|
||||||
|
input force_stop,
|
||||||
output [COUNTER_MAX_WID-1:0] cntr,
|
output [COUNTER_MAX_WID-1:0] cntr,
|
||||||
input do_loop,
|
input do_loop,
|
||||||
output finished,
|
output finished,
|
||||||
|
@ -52,6 +53,7 @@ waveform #(
|
||||||
) wf (
|
) wf (
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.run(run),
|
.run(run),
|
||||||
|
.force_stop(force_stop),
|
||||||
.cntr(cntr),
|
.cntr(cntr),
|
||||||
.do_loop(do_loop),
|
.do_loop(do_loop),
|
||||||
.finished(finished),
|
.finished(finished),
|
||||||
|
|
|
@ -274,7 +274,7 @@ class UpsilonSoC(SoCCore):
|
||||||
def f(csrs):
|
def f(csrs):
|
||||||
wid = kwargs["spi_wid"]
|
wid = kwargs["spi_wid"]
|
||||||
origin = csrs["memories"][name.lower() + "_pi"]['base']
|
origin = csrs["memories"][name.lower() + "_pi"]['base']
|
||||||
return f'{name} = SPI({wid}, {origin}, {spi.mmio(origin)})'
|
return f'{name} = SPI({wid}, {name}_PI, {origin}, {spi.mmio(origin)})'
|
||||||
self.mmio_closures.append(f)
|
self.mmio_closures.append(f)
|
||||||
|
|
||||||
return spi, pi
|
return spi, pi
|
||||||
|
|
22
linux/spi.py
22
linux/spi.py
|
@ -1,6 +1,26 @@
|
||||||
from registers import *
|
from registers import *
|
||||||
|
|
||||||
class SPI(RegisterRegion):
|
class SPI(RegisterRegion):
|
||||||
def __init__(self, spiwid, origin, **regs):
|
def __init__(self, spiwid, spi_PI, origin, **regs):
|
||||||
self.spiwid = spiwid
|
self.spiwid = spiwid
|
||||||
|
self.spi_PI = spi_PI
|
||||||
super().__init__(origin, **regs)
|
super().__init__(origin, **regs)
|
||||||
|
|
||||||
|
def send(self, val, force=False):
|
||||||
|
if self.spi_PI.v != 0 and not force:
|
||||||
|
raise Exception("SPI is controlled by another master")
|
||||||
|
|
||||||
|
self.spi_PI.v = 0
|
||||||
|
|
||||||
|
self.arm.v = 0
|
||||||
|
while self.finished_or_ready.v == 0:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.to_slave.v = val
|
||||||
|
self.arm.v = 1
|
||||||
|
while self.finished_or_ready.v == 0:
|
||||||
|
pass
|
||||||
|
|
||||||
|
read_val = self.from_slave.v
|
||||||
|
self.arm.v = 0
|
||||||
|
return read_val
|
||||||
|
|
|
@ -38,6 +38,10 @@ class Waveform(Immutable):
|
||||||
while self.regs.finished_or_ready == 0:
|
while self.regs.finished_or_ready == 0:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def force_stop(self):
|
||||||
|
self.regs.force_stop = 1
|
||||||
|
selff.regs.force_stop = 0
|
||||||
|
|
||||||
def dump(self):
|
def dump(self):
|
||||||
""" Dump contents of control registers. """
|
""" Dump contents of control registers. """
|
||||||
return self.regs.dump()
|
return self.regs.dump()
|
||||||
|
|
Loading…
Reference in New Issue