sw: first software commit
The software is untested, but it builds. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
		
							
								
								
									
										14
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,21 +1,21 @@
 | 
				
			|||||||
[submodule "deps/migen"]
 | 
					[submodule "deps/migen"]
 | 
				
			||||||
	path = deps/migen
 | 
						path = hw/deps/migen
 | 
				
			||||||
	url = https://github.com/m-labs/migen.git
 | 
						url = https://github.com/m-labs/migen.git
 | 
				
			||||||
[submodule "deps/litex"]
 | 
					[submodule "deps/litex"]
 | 
				
			||||||
	path = deps/litex
 | 
						path = hw/deps/litex
 | 
				
			||||||
	url = https://github.com/enjoy-digital/litex.git
 | 
						url = https://github.com/enjoy-digital/litex.git
 | 
				
			||||||
[submodule "deps/litescope"]
 | 
					[submodule "deps/litescope"]
 | 
				
			||||||
	path = deps/litescope
 | 
						path = hw/deps/litescope
 | 
				
			||||||
	url = https://github.com/enjoy-digital/litescope.git
 | 
						url = https://github.com/enjoy-digital/litescope.git
 | 
				
			||||||
[submodule "deps/pyserial"]
 | 
					[submodule "deps/pyserial"]
 | 
				
			||||||
	path = deps/pyserial
 | 
						path = hw/deps/pyserial
 | 
				
			||||||
	url = https://github.com/pyserial/pyserial.git
 | 
						url = https://github.com/pyserial/pyserial.git
 | 
				
			||||||
[submodule "deps/litedram"]
 | 
					[submodule "deps/litedram"]
 | 
				
			||||||
	path = deps/litedram
 | 
						path = hw/deps/litedram
 | 
				
			||||||
	url = https://github.com/enjoy-digital/litedram.git
 | 
						url = https://github.com/enjoy-digital/litedram.git
 | 
				
			||||||
[submodule "deps/valentyusb"]
 | 
					[submodule "deps/valentyusb"]
 | 
				
			||||||
	path = deps/valentyusb
 | 
						path = hw/deps/valentyusb
 | 
				
			||||||
	url = https://github.com/im-tomu/valentyusb.git
 | 
						url = https://github.com/im-tomu/valentyusb.git
 | 
				
			||||||
[submodule "deps/lxsocsupport"]
 | 
					[submodule "deps/lxsocsupport"]
 | 
				
			||||||
	path = deps/lxsocsupport
 | 
						path = hw/deps/lxsocsupport
 | 
				
			||||||
	url = https://github.com/xobs/lxsocsupport.git
 | 
						url = https://github.com/xobs/lxsocsupport.git
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -87,7 +87,8 @@ _io_evt = [
 | 
				
			|||||||
    ),
 | 
					    ),
 | 
				
			||||||
    ("clk48", 0, Pins("44"), IOStandard("LVCMOS33"))
 | 
					    ("clk48", 0, Pins("44"), IOStandard("LVCMOS33"))
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
_io_dvt = [
 | 
					
 | 
				
			||||||
 | 
					_io_pvt = [
 | 
				
			||||||
    ("serial", 0,
 | 
					    ("serial", 0,
 | 
				
			||||||
        Subsignal("rx", Pins("C3")),
 | 
					        Subsignal("rx", Pins("C3")),
 | 
				
			||||||
        Subsignal("tx", Pins("B3"), Misc("PULLUP")),
 | 
					        Subsignal("tx", Pins("B3"), Misc("PULLUP")),
 | 
				
			||||||
@@ -125,6 +126,7 @@ _io_dvt = [
 | 
				
			|||||||
    ),
 | 
					    ),
 | 
				
			||||||
    ("clk48", 0, Pins("F4"), IOStandard("LVCMOS33"))
 | 
					    ("clk48", 0, Pins("F4"), IOStandard("LVCMOS33"))
 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
_io_hacker = [
 | 
					_io_hacker = [
 | 
				
			||||||
    ("serial", 0,
 | 
					    ("serial", 0,
 | 
				
			||||||
        Subsignal("rx", Pins("C3")),
 | 
					        Subsignal("rx", Pins("C3")),
 | 
				
			||||||
@@ -197,7 +199,6 @@ class _CRG(Module):
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if use_pll:
 | 
					        if use_pll:
 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Divide clk48 down to clk12, to ensure they're synchronized.
 | 
					            # Divide clk48 down to clk12, to ensure they're synchronized.
 | 
				
			||||||
            # By doing this, we avoid needing clock-domain crossing.
 | 
					            # By doing this, we avoid needing clock-domain crossing.
 | 
				
			||||||
            clk12_counter = Signal(2)
 | 
					            clk12_counter = Signal(2)
 | 
				
			||||||
@@ -316,12 +317,12 @@ class Platform(LatticePlatform):
 | 
				
			|||||||
    def __init__(self, revision=None, toolchain="icestorm"):
 | 
					    def __init__(self, revision=None, toolchain="icestorm"):
 | 
				
			||||||
        if revision == "evt":
 | 
					        if revision == "evt":
 | 
				
			||||||
            LatticePlatform.__init__(self, "ice40-up5k-sg48", _io_evt, _connectors, toolchain="icestorm")
 | 
					            LatticePlatform.__init__(self, "ice40-up5k-sg48", _io_evt, _connectors, toolchain="icestorm")
 | 
				
			||||||
        elif revision == "dvt":
 | 
					        elif revision == "pvt" or revision == "dvt":
 | 
				
			||||||
            LatticePlatform.__init__(self, "ice40-up5k-uwg30", _io_dvt, _connectors, toolchain="icestorm")
 | 
					            LatticePlatform.__init__(self, "ice40-up5k-uwg30", _io_pvt, _connectors, toolchain="icestorm")
 | 
				
			||||||
        elif revision == "hacker":
 | 
					        elif revision == "hacker":
 | 
				
			||||||
            LatticePlatform.__init__(self, "ice40-up5k-uwg30", _io_hacker, _connectors, toolchain="icestorm")
 | 
					            LatticePlatform.__init__(self, "ice40-up5k-uwg30", _io_hacker, _connectors, toolchain="icestorm")
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            raise ValueError("Unrecognized reivsion: {}.  Known values: evt, dvt, hacker".format(revision))
 | 
					            raise ValueError("Unrecognized reivsion: {}.  Known values: evt, dvt, pvt, hacker".format(revision))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def create_programmer(self):
 | 
					    def create_programmer(self):
 | 
				
			||||||
        raise ValueError("programming is not supported")
 | 
					        raise ValueError("programming is not supported")
 | 
				
			||||||
@@ -593,8 +594,14 @@ class Version(Module, AutoCSR):
 | 
				
			|||||||
                                stderr=subprocess.PIPE)
 | 
					                                stderr=subprocess.PIPE)
 | 
				
			||||||
            (git_stdout, _) = git_rev_cmd.communicate()
 | 
					            (git_stdout, _) = git_rev_cmd.communicate()
 | 
				
			||||||
            if git_rev_cmd.wait() != 0:
 | 
					            if git_rev_cmd.wait() != 0:
 | 
				
			||||||
                print('unable to get git version')
 | 
					                git_rev_cmd = subprocess.Popen(["git", "rev-parse", "HEAD"],
 | 
				
			||||||
                return
 | 
					                    stdout=subprocess.PIPE,
 | 
				
			||||||
 | 
					                    stderr=subprocess.PIPE)
 | 
				
			||||||
 | 
					                (git_stdout, _) = git_rev_cmd.communicate()
 | 
				
			||||||
 | 
					                if git_rev_cmd.wait() != 0:
 | 
				
			||||||
 | 
					                    print('WARNING: unable to get git version')
 | 
				
			||||||
 | 
					                    return (0, 0, 0, 0, 0, False)
 | 
				
			||||||
 | 
					                return (0, 0, 0, makeint(git_stdout[0:8], 16), 0, False)
 | 
				
			||||||
            raw_git_rev = git_stdout.decode().strip()
 | 
					            raw_git_rev = git_stdout.decode().strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            dirty = False
 | 
					            dirty = False
 | 
				
			||||||
@@ -773,8 +780,6 @@ class BaseSoC(SoCCore):
 | 
				
			|||||||
            pulldown = TSTriple()
 | 
					            pulldown = TSTriple()
 | 
				
			||||||
            self.specials += pulldown.get_tristate(usb_pads.pulldown)
 | 
					            self.specials += pulldown.get_tristate(usb_pads.pulldown)
 | 
				
			||||||
            self.comb += pulldown.oe.eq(0)
 | 
					            self.comb += pulldown.oe.eq(0)
 | 
				
			||||||
        # self.submodules.usb = epmem.MemInterface(usb_iobuf)
 | 
					 | 
				
			||||||
        # self.submodules.usb = unififo.UsbUniFifo(usb_iobuf)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Add GPIO pads for the touch buttons
 | 
					        # Add GPIO pads for the touch buttons
 | 
				
			||||||
        self.submodules.touch = TouchPads(platform.request("touch"))
 | 
					        self.submodules.touch = TouchPads(platform.request("touch"))
 | 
				
			||||||
@@ -784,7 +789,7 @@ class BaseSoC(SoCCore):
 | 
				
			|||||||
        # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
 | 
					        # and the "-dffe_min_ce_use 4" flag prevents Yosys from generating a
 | 
				
			||||||
        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
 | 
					        # Clock Enable signal for a LUT that has fewer than 4 flip-flops.
 | 
				
			||||||
        # This increases density, and lets us use the FPGA more efficiently.
 | 
					        # This increases density, and lets us use the FPGA more efficiently.
 | 
				
			||||||
        platform.toolchain.nextpnr_yosys_template[2] += " -relut -dffe_min_ce_use 5"
 | 
					        platform.toolchain.nextpnr_yosys_template[2] += " -relut -dffe_min_ce_use 4"
 | 
				
			||||||
        if use_dsp:
 | 
					        if use_dsp:
 | 
				
			||||||
            platform.toolchain.nextpnr_yosys_template[2] += " -dsp"
 | 
					            platform.toolchain.nextpnr_yosys_template[2] += " -dsp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -813,7 +818,7 @@ def main():
 | 
				
			|||||||
        help="where to have the CPU obtain its executable code from"
 | 
					        help="where to have the CPU obtain its executable code from"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser.add_argument(
 | 
					    parser.add_argument(
 | 
				
			||||||
        "--revision", choices=["dvt", "evt", "hacker"], required=True,
 | 
					        "--revision", choices=["pvt", "dvt", "evt", "hacker"], required=True,
 | 
				
			||||||
        help="build foboot for a particular hardware revision"
 | 
					        help="build foboot for a particular hardware revision"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser.add_argument(
 | 
					    parser.add_argument(
 | 
				
			||||||
@@ -834,35 +839,10 @@ def main():
 | 
				
			|||||||
    parser.add_argument(
 | 
					    parser.add_argument(
 | 
				
			||||||
        "--placer", choices=["sa", "heap"], help="which placer to use in nextpnr"
 | 
					        "--placer", choices=["sa", "heap"], help="which placer to use in nextpnr"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    parser.add_argument(
 | 
					 | 
				
			||||||
        "--export-random-rom-file", help="Generate a random ROM file and save it to a file"
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    args = parser.parse_args()
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    output_dir = 'build'
 | 
					    output_dir = 'build'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if args.export_random_rom_file is not None:
 | 
					 | 
				
			||||||
        size = 0x2000
 | 
					 | 
				
			||||||
        def xorshift32(x):
 | 
					 | 
				
			||||||
            x = x ^ (x << 13) & 0xffffffff
 | 
					 | 
				
			||||||
            x = x ^ (x >> 17) & 0xffffffff
 | 
					 | 
				
			||||||
            x = x ^ (x << 5)  & 0xffffffff
 | 
					 | 
				
			||||||
            return x & 0xffffffff
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def get_rand(x):
 | 
					 | 
				
			||||||
            out = 0
 | 
					 | 
				
			||||||
            for i in range(32):
 | 
					 | 
				
			||||||
                x = xorshift32(x)
 | 
					 | 
				
			||||||
                if (x & 1) == 1:
 | 
					 | 
				
			||||||
                    out = out | (1 << i)
 | 
					 | 
				
			||||||
            return out & 0xffffffff
 | 
					 | 
				
			||||||
        seed = 1
 | 
					 | 
				
			||||||
        with open(args.export_random_rom_file, "w", newline="\n") as output:
 | 
					 | 
				
			||||||
            for d in range(int(size / 4)):
 | 
					 | 
				
			||||||
                seed = get_rand(seed)
 | 
					 | 
				
			||||||
                print("{:08x}".format(seed), file=output)
 | 
					 | 
				
			||||||
        return 0
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    compile_software = False
 | 
					    compile_software = False
 | 
				
			||||||
    if args.boot_source == "bios" and args.bios is None:
 | 
					    if args.boot_source == "bios" and args.bios is None:
 | 
				
			||||||
        compile_software = True
 | 
					        compile_software = True
 | 
				
			||||||
							
								
								
									
										3578
									
								
								hw/rtl/2-stage-1024-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3578
									
								
								hw/rtl/2-stage-1024-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								hw/rtl/2-stage-1024-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								hw/rtl/2-stage-1024-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [4111, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 1024}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3289
									
								
								hw/rtl/2-stage-1024-cache.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3289
									
								
								hw/rtl/2-stage-1024-cache.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4
									
								
								hw/rtl/2-stage-1024-cache.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								hw/rtl/2-stage-1024-cache.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [4111, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 1024}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3578
									
								
								hw/rtl/2-stage-2048-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3578
									
								
								hw/rtl/2-stage-2048-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								hw/rtl/2-stage-2048-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								hw/rtl/2-stage-2048-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [4111, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 2048}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3297
									
								
								hw/rtl/2-stage-2048-cache.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3297
									
								
								hw/rtl/2-stage-2048-cache.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4
									
								
								hw/rtl/2-stage-2048-cache.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								hw/rtl/2-stage-2048-cache.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [4111, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 2048}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3769
									
								
								hw/rtl/2-stage-512-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3769
									
								
								hw/rtl/2-stage-512-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								hw/rtl/2-stage-512-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								hw/rtl/2-stage-512-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [16399, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 512}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3499
									
								
								hw/rtl/2-stage-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3499
									
								
								hw/rtl/2-stage-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								hw/rtl/2-stage-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								hw/rtl/2-stage-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
							
								
								
									
										3965
									
								
								hw/rtl/4-stage-1024-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3965
									
								
								hw/rtl/4-stage-1024-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								hw/rtl/4-stage-1024-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								hw/rtl/4-stage-1024-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
 | 
					iBus: !!vexriscv.BusReport
 | 
				
			||||||
 | 
					  flushInstructions: [4111, 19, 19, 19]
 | 
				
			||||||
 | 
					  info: !!vexriscv.CacheReport {bytePerLine: 32, size: 1024}
 | 
				
			||||||
 | 
					  kind: cached
 | 
				
			||||||
							
								
								
									
										3865
									
								
								hw/rtl/4-stage-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3865
									
								
								hw/rtl/4-stage-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								hw/rtl/4-stage-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								hw/rtl/4-stage-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
							
								
								
									
										3902
									
								
								hw/rtl/5-stage-pipelined-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3902
									
								
								hw/rtl/5-stage-pipelined-no-cache-debug.v
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1
									
								
								hw/rtl/5-stage-pipelined-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								hw/rtl/5-stage-pipelined-no-cache-debug.yaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					debug: !!vexriscv.DebugReport {hardwareBreakpointCount: 4}
 | 
				
			||||||
							
								
								
									
										579
									
								
								hw/rtl/spimemio.v
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										579
									
								
								hw/rtl/spimemio.v
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,579 @@
 | 
				
			|||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *  PicoSoC - A simple example SoC using PicoRV32
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Copyright (C) 2017  Clifford Wolf <clifford@clifford.at>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
				
			||||||
 | 
					 *  purpose with or without fee is hereby granted, provided that the above
 | 
				
			||||||
 | 
					 *  copyright notice and this permission notice appear in all copies.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
				
			||||||
 | 
					 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
				
			||||||
 | 
					 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
				
			||||||
 | 
					 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
				
			||||||
 | 
					 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
				
			||||||
 | 
					 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
				
			||||||
 | 
					 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module spimemio (
 | 
				
			||||||
 | 
						input clk, resetn,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input valid,
 | 
				
			||||||
 | 
						output ready,
 | 
				
			||||||
 | 
						input [23:0] addr,
 | 
				
			||||||
 | 
						output reg [31:0] rdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output flash_csb,
 | 
				
			||||||
 | 
						output flash_clk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output flash_io0_oe,
 | 
				
			||||||
 | 
						output flash_io1_oe,
 | 
				
			||||||
 | 
						output flash_io2_oe,
 | 
				
			||||||
 | 
						output flash_io3_oe,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output flash_io0_do,
 | 
				
			||||||
 | 
						output flash_io1_do,
 | 
				
			||||||
 | 
						output flash_io2_do,
 | 
				
			||||||
 | 
						output flash_io3_do,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input  flash_io0_di,
 | 
				
			||||||
 | 
						input  flash_io1_di,
 | 
				
			||||||
 | 
						input  flash_io2_di,
 | 
				
			||||||
 | 
						input  flash_io3_di,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input   [3:0] cfgreg_we,
 | 
				
			||||||
 | 
						input  [31:0] cfgreg_di,
 | 
				
			||||||
 | 
						output [31:0] cfgreg_do
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						reg        xfer_resetn;
 | 
				
			||||||
 | 
						reg        din_valid;
 | 
				
			||||||
 | 
						wire       din_ready;
 | 
				
			||||||
 | 
						reg  [7:0] din_data;
 | 
				
			||||||
 | 
						reg  [3:0] din_tag;
 | 
				
			||||||
 | 
						reg        din_cont;
 | 
				
			||||||
 | 
						reg        din_qspi;
 | 
				
			||||||
 | 
						reg        din_ddr;
 | 
				
			||||||
 | 
						reg        din_rd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wire       dout_valid;
 | 
				
			||||||
 | 
						wire [7:0] dout_data;
 | 
				
			||||||
 | 
						wire [3:0] dout_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg [23:0] buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg [23:0] rd_addr;
 | 
				
			||||||
 | 
						reg rd_valid;
 | 
				
			||||||
 | 
						reg rd_wait;
 | 
				
			||||||
 | 
						reg rd_inc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign ready = valid && (addr == rd_addr) && rd_valid;
 | 
				
			||||||
 | 
						wire jump = valid && !ready && (addr != rd_addr+4) && rd_valid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg softreset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg       config_en;      // cfgreg[31]
 | 
				
			||||||
 | 
						reg       config_ddr;     // cfgreg[22]
 | 
				
			||||||
 | 
						reg       config_qspi;    // cfgreg[21]
 | 
				
			||||||
 | 
						reg       config_cont;    // cfgreg[20]
 | 
				
			||||||
 | 
						reg [3:0] config_dummy;   // cfgreg[19:16]
 | 
				
			||||||
 | 
						reg [3:0] config_oe;      // cfgreg[11:8]
 | 
				
			||||||
 | 
						reg       config_csb;     // cfgreg[5]
 | 
				
			||||||
 | 
						reg       config_clk;     // cfgref[4]
 | 
				
			||||||
 | 
						reg [3:0] config_do;      // cfgreg[3:0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign cfgreg_do[31] = config_en;
 | 
				
			||||||
 | 
						assign cfgreg_do[30:23] = 0;
 | 
				
			||||||
 | 
						assign cfgreg_do[22] = config_ddr;
 | 
				
			||||||
 | 
						assign cfgreg_do[21] = config_qspi;
 | 
				
			||||||
 | 
						assign cfgreg_do[20] = config_cont;
 | 
				
			||||||
 | 
						assign cfgreg_do[19:16] = config_dummy;
 | 
				
			||||||
 | 
						assign cfgreg_do[15:12] = 0;
 | 
				
			||||||
 | 
						assign cfgreg_do[11:8] = {flash_io3_oe, flash_io2_oe, flash_io1_oe, flash_io0_oe};
 | 
				
			||||||
 | 
						assign cfgreg_do[7:6] = 0;
 | 
				
			||||||
 | 
						assign cfgreg_do[5] = flash_csb;
 | 
				
			||||||
 | 
						assign cfgreg_do[4] = flash_clk;
 | 
				
			||||||
 | 
						assign cfgreg_do[3:0] = {flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @(posedge clk) begin
 | 
				
			||||||
 | 
							softreset <= !config_en || cfgreg_we;
 | 
				
			||||||
 | 
							if (!resetn) begin
 | 
				
			||||||
 | 
								softreset <= 1;
 | 
				
			||||||
 | 
								config_en <= 1;
 | 
				
			||||||
 | 
								config_csb <= 0;
 | 
				
			||||||
 | 
								config_clk <= 0;
 | 
				
			||||||
 | 
								config_oe <= 0;
 | 
				
			||||||
 | 
								config_do <= 0;
 | 
				
			||||||
 | 
								config_ddr <= 0;
 | 
				
			||||||
 | 
								config_qspi <= 0;
 | 
				
			||||||
 | 
								config_cont <= 0;
 | 
				
			||||||
 | 
								config_dummy <= 8;
 | 
				
			||||||
 | 
							end else begin
 | 
				
			||||||
 | 
								if (cfgreg_we[0]) begin
 | 
				
			||||||
 | 
									config_csb <= cfgreg_di[5];
 | 
				
			||||||
 | 
									config_clk <= cfgreg_di[4];
 | 
				
			||||||
 | 
									config_do <= cfgreg_di[3:0];
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								if (cfgreg_we[1]) begin
 | 
				
			||||||
 | 
									config_oe <= cfgreg_di[11:8];
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								if (cfgreg_we[2]) begin
 | 
				
			||||||
 | 
									config_ddr <= cfgreg_di[22];
 | 
				
			||||||
 | 
									config_qspi <= cfgreg_di[21];
 | 
				
			||||||
 | 
									config_cont <= cfgreg_di[20];
 | 
				
			||||||
 | 
									config_dummy <= cfgreg_di[19:16];
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								if (cfgreg_we[3]) begin
 | 
				
			||||||
 | 
									config_en <= cfgreg_di[31];
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wire xfer_csb;
 | 
				
			||||||
 | 
						wire xfer_clk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wire xfer_io0_oe;
 | 
				
			||||||
 | 
						wire xfer_io1_oe;
 | 
				
			||||||
 | 
						wire xfer_io2_oe;
 | 
				
			||||||
 | 
						wire xfer_io3_oe;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wire xfer_io0_do;
 | 
				
			||||||
 | 
						wire xfer_io1_do;
 | 
				
			||||||
 | 
						wire xfer_io2_do;
 | 
				
			||||||
 | 
						wire xfer_io3_do;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg xfer_io0_90;
 | 
				
			||||||
 | 
						reg xfer_io1_90;
 | 
				
			||||||
 | 
						reg xfer_io2_90;
 | 
				
			||||||
 | 
						reg xfer_io3_90;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @(negedge clk) begin
 | 
				
			||||||
 | 
							xfer_io0_90 <= xfer_io0_do;
 | 
				
			||||||
 | 
							xfer_io1_90 <= xfer_io1_do;
 | 
				
			||||||
 | 
							xfer_io2_90 <= xfer_io2_do;
 | 
				
			||||||
 | 
							xfer_io3_90 <= xfer_io3_do;
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign flash_csb = config_en ? xfer_csb : config_csb;
 | 
				
			||||||
 | 
						assign flash_clk = config_en ? xfer_clk : config_clk;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign flash_io0_oe = config_en ? xfer_io0_oe : config_oe[0];
 | 
				
			||||||
 | 
						assign flash_io1_oe = config_en ? xfer_io1_oe : config_oe[1];
 | 
				
			||||||
 | 
						assign flash_io2_oe = config_en ? xfer_io2_oe : config_oe[2];
 | 
				
			||||||
 | 
						assign flash_io3_oe = config_en ? xfer_io3_oe : config_oe[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign flash_io0_do = config_en ? (config_ddr ? xfer_io0_90 : xfer_io0_do) : config_do[0];
 | 
				
			||||||
 | 
						assign flash_io1_do = config_en ? (config_ddr ? xfer_io1_90 : xfer_io1_do) : config_do[1];
 | 
				
			||||||
 | 
						assign flash_io2_do = config_en ? (config_ddr ? xfer_io2_90 : xfer_io2_do) : config_do[2];
 | 
				
			||||||
 | 
						assign flash_io3_do = config_en ? (config_ddr ? xfer_io3_90 : xfer_io3_do) : config_do[3];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						wire xfer_dspi = din_ddr && !din_qspi;
 | 
				
			||||||
 | 
						wire xfer_ddr = din_ddr && din_qspi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spimemio_xfer xfer (
 | 
				
			||||||
 | 
							.clk          (clk         ),
 | 
				
			||||||
 | 
							.resetn       (xfer_resetn ),
 | 
				
			||||||
 | 
							.din_valid    (din_valid   ),
 | 
				
			||||||
 | 
							.din_ready    (din_ready   ),
 | 
				
			||||||
 | 
							.din_data     (din_data    ),
 | 
				
			||||||
 | 
							.din_tag      (din_tag     ),
 | 
				
			||||||
 | 
							.din_cont     (din_cont    ),
 | 
				
			||||||
 | 
							.din_dspi     (xfer_dspi   ),
 | 
				
			||||||
 | 
							.din_qspi     (din_qspi    ),
 | 
				
			||||||
 | 
							.din_ddr      (xfer_ddr    ),
 | 
				
			||||||
 | 
							.din_rd       (din_rd      ),
 | 
				
			||||||
 | 
							.dout_valid   (dout_valid  ),
 | 
				
			||||||
 | 
							.dout_data    (dout_data   ),
 | 
				
			||||||
 | 
							.dout_tag     (dout_tag    ),
 | 
				
			||||||
 | 
							.flash_csb    (xfer_csb    ),
 | 
				
			||||||
 | 
							.flash_clk    (xfer_clk    ),
 | 
				
			||||||
 | 
							.flash_io0_oe (xfer_io0_oe ),
 | 
				
			||||||
 | 
							.flash_io1_oe (xfer_io1_oe ),
 | 
				
			||||||
 | 
							.flash_io2_oe (xfer_io2_oe ),
 | 
				
			||||||
 | 
							.flash_io3_oe (xfer_io3_oe ),
 | 
				
			||||||
 | 
							.flash_io0_do (xfer_io0_do ),
 | 
				
			||||||
 | 
							.flash_io1_do (xfer_io1_do ),
 | 
				
			||||||
 | 
							.flash_io2_do (xfer_io2_do ),
 | 
				
			||||||
 | 
							.flash_io3_do (xfer_io3_do ),
 | 
				
			||||||
 | 
							.flash_io0_di (flash_io0_di),
 | 
				
			||||||
 | 
							.flash_io1_di (flash_io1_di),
 | 
				
			||||||
 | 
							.flash_io2_di (flash_io2_di),
 | 
				
			||||||
 | 
							.flash_io3_di (flash_io3_di)
 | 
				
			||||||
 | 
						);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg [3:0] state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @(posedge clk) begin
 | 
				
			||||||
 | 
							xfer_resetn <= 1;
 | 
				
			||||||
 | 
							din_valid <= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!resetn || softreset) begin
 | 
				
			||||||
 | 
								state <= 0;
 | 
				
			||||||
 | 
								xfer_resetn <= 0;
 | 
				
			||||||
 | 
								rd_valid <= 0;
 | 
				
			||||||
 | 
								din_tag <= 0;
 | 
				
			||||||
 | 
								din_cont <= 0;
 | 
				
			||||||
 | 
								din_qspi <= 0;
 | 
				
			||||||
 | 
								din_ddr <= 0;
 | 
				
			||||||
 | 
								din_rd <= 0;
 | 
				
			||||||
 | 
							end else begin
 | 
				
			||||||
 | 
								if (dout_valid && dout_tag == 1) buffer[ 7: 0] <= dout_data;
 | 
				
			||||||
 | 
								if (dout_valid && dout_tag == 2) buffer[15: 8] <= dout_data;
 | 
				
			||||||
 | 
								if (dout_valid && dout_tag == 3) buffer[23:16] <= dout_data;
 | 
				
			||||||
 | 
								if (dout_valid && dout_tag == 4) begin
 | 
				
			||||||
 | 
									rdata <= {dout_data, buffer};
 | 
				
			||||||
 | 
									rd_addr <= rd_inc ? rd_addr + 4 : addr;
 | 
				
			||||||
 | 
									rd_valid <= 1;
 | 
				
			||||||
 | 
									rd_wait <= rd_inc;
 | 
				
			||||||
 | 
									rd_inc <= 1;
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (valid)
 | 
				
			||||||
 | 
									rd_wait <= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								case (state)
 | 
				
			||||||
 | 
									0: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_data <= 8'h ff;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 1;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									1: begin
 | 
				
			||||||
 | 
										if (dout_valid) begin
 | 
				
			||||||
 | 
											xfer_resetn <= 0;
 | 
				
			||||||
 | 
											state <= 2;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									2: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_data <= 8'h ab;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 3;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									3: begin
 | 
				
			||||||
 | 
										if (dout_valid) begin
 | 
				
			||||||
 | 
											xfer_resetn <= 0;
 | 
				
			||||||
 | 
											state <= 4;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									4: begin
 | 
				
			||||||
 | 
										rd_inc <= 0;
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										case ({config_ddr, config_qspi})
 | 
				
			||||||
 | 
											2'b11: din_data <= 8'h ED;
 | 
				
			||||||
 | 
											2'b01: din_data <= 8'h EB;
 | 
				
			||||||
 | 
											2'b10: din_data <= 8'h BB;
 | 
				
			||||||
 | 
											2'b00: din_data <= 8'h 03;
 | 
				
			||||||
 | 
										endcase
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 5;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									5: begin
 | 
				
			||||||
 | 
										if (valid && !ready) begin
 | 
				
			||||||
 | 
											din_valid <= 1;
 | 
				
			||||||
 | 
											din_tag <= 0;
 | 
				
			||||||
 | 
											din_data <= addr[23:16];
 | 
				
			||||||
 | 
											din_qspi <= config_qspi;
 | 
				
			||||||
 | 
											din_ddr <= config_ddr;
 | 
				
			||||||
 | 
											if (din_ready) begin
 | 
				
			||||||
 | 
												din_valid <= 0;
 | 
				
			||||||
 | 
												state <= 6;
 | 
				
			||||||
 | 
											end
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									6: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										din_data <= addr[15:8];
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 7;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									7: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										din_data <= addr[7:0];
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											din_data <= 0;
 | 
				
			||||||
 | 
											state <= config_qspi || config_ddr ? 8 : 9;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									8: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 0;
 | 
				
			||||||
 | 
										din_data <= config_cont ? 8'h A5 : 8'h FF;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_rd <= 1;
 | 
				
			||||||
 | 
											din_data <= config_dummy;
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 9;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									9: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 1;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 10;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									10: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_data <= 8'h 00;
 | 
				
			||||||
 | 
										din_tag <= 2;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 11;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									11: begin
 | 
				
			||||||
 | 
										din_valid <= 1;
 | 
				
			||||||
 | 
										din_tag <= 3;
 | 
				
			||||||
 | 
										if (din_ready) begin
 | 
				
			||||||
 | 
											din_valid <= 0;
 | 
				
			||||||
 | 
											state <= 12;
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									12: begin
 | 
				
			||||||
 | 
										if (!rd_wait || valid) begin
 | 
				
			||||||
 | 
											din_valid <= 1;
 | 
				
			||||||
 | 
											din_tag <= 4;
 | 
				
			||||||
 | 
											if (din_ready) begin
 | 
				
			||||||
 | 
												din_valid <= 0;
 | 
				
			||||||
 | 
												state <= 9;
 | 
				
			||||||
 | 
											end
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
								endcase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (jump) begin
 | 
				
			||||||
 | 
									rd_inc <= 0;
 | 
				
			||||||
 | 
									rd_valid <= 0;
 | 
				
			||||||
 | 
									xfer_resetn <= 0;
 | 
				
			||||||
 | 
									if (config_cont) begin
 | 
				
			||||||
 | 
										state <= 5;
 | 
				
			||||||
 | 
									end else begin
 | 
				
			||||||
 | 
										state <= 4;
 | 
				
			||||||
 | 
										din_qspi <= 0;
 | 
				
			||||||
 | 
										din_ddr <= 0;
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									din_rd <= 0;
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module spimemio_xfer (
 | 
				
			||||||
 | 
						input clk, resetn,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input            din_valid,
 | 
				
			||||||
 | 
						output           din_ready,
 | 
				
			||||||
 | 
						input      [7:0] din_data,
 | 
				
			||||||
 | 
						input      [3:0] din_tag,
 | 
				
			||||||
 | 
						input            din_cont,
 | 
				
			||||||
 | 
						input            din_dspi,
 | 
				
			||||||
 | 
						input            din_qspi,
 | 
				
			||||||
 | 
						input            din_ddr,
 | 
				
			||||||
 | 
						input            din_rd,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output           dout_valid,
 | 
				
			||||||
 | 
						output     [7:0] dout_data,
 | 
				
			||||||
 | 
						output     [3:0] dout_tag,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output reg flash_csb,
 | 
				
			||||||
 | 
						output reg flash_clk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output reg flash_io0_oe,
 | 
				
			||||||
 | 
						output reg flash_io1_oe,
 | 
				
			||||||
 | 
						output reg flash_io2_oe,
 | 
				
			||||||
 | 
						output reg flash_io3_oe,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						output reg flash_io0_do,
 | 
				
			||||||
 | 
						output reg flash_io1_do,
 | 
				
			||||||
 | 
						output reg flash_io2_do,
 | 
				
			||||||
 | 
						output reg flash_io3_do,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						input      flash_io0_di,
 | 
				
			||||||
 | 
						input      flash_io1_di,
 | 
				
			||||||
 | 
						input      flash_io2_di,
 | 
				
			||||||
 | 
						input      flash_io3_di
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
						reg [7:0] obuffer;
 | 
				
			||||||
 | 
						reg [7:0] ibuffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg [3:0] count;
 | 
				
			||||||
 | 
						reg [3:0] dummy_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg xfer_cont;
 | 
				
			||||||
 | 
						reg xfer_dspi;
 | 
				
			||||||
 | 
						reg xfer_qspi;
 | 
				
			||||||
 | 
						reg xfer_ddr;
 | 
				
			||||||
 | 
						reg xfer_ddr_q;
 | 
				
			||||||
 | 
						reg xfer_rd;
 | 
				
			||||||
 | 
						reg [3:0] xfer_tag;
 | 
				
			||||||
 | 
						reg [3:0] xfer_tag_q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg [7:0] next_obuffer;
 | 
				
			||||||
 | 
						reg [7:0] next_ibuffer;
 | 
				
			||||||
 | 
						reg [3:0] next_count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						reg fetch;
 | 
				
			||||||
 | 
						reg next_fetch;
 | 
				
			||||||
 | 
						reg last_fetch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @(posedge clk) begin
 | 
				
			||||||
 | 
							xfer_ddr_q <= xfer_ddr;
 | 
				
			||||||
 | 
							xfer_tag_q <= xfer_tag;
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign din_ready = din_valid && resetn && next_fetch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assign dout_valid = (xfer_ddr_q ? fetch && !last_fetch : next_fetch && !fetch) && resetn;
 | 
				
			||||||
 | 
						assign dout_data = ibuffer;
 | 
				
			||||||
 | 
						assign dout_tag = xfer_tag_q;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @* begin
 | 
				
			||||||
 | 
							flash_io0_oe = 0;
 | 
				
			||||||
 | 
							flash_io1_oe = 0;
 | 
				
			||||||
 | 
							flash_io2_oe = 0;
 | 
				
			||||||
 | 
							flash_io3_oe = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							flash_io0_do = 0;
 | 
				
			||||||
 | 
							flash_io1_do = 0;
 | 
				
			||||||
 | 
							flash_io2_do = 0;
 | 
				
			||||||
 | 
							flash_io3_do = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							next_obuffer = obuffer;
 | 
				
			||||||
 | 
							next_ibuffer = ibuffer;
 | 
				
			||||||
 | 
							next_count = count;
 | 
				
			||||||
 | 
							next_fetch = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (dummy_count == 0) begin
 | 
				
			||||||
 | 
								casez ({xfer_ddr, xfer_qspi, xfer_dspi})
 | 
				
			||||||
 | 
									3'b 000: begin
 | 
				
			||||||
 | 
										flash_io0_oe = 1;
 | 
				
			||||||
 | 
										flash_io0_do = obuffer[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (flash_clk) begin
 | 
				
			||||||
 | 
											next_obuffer = {obuffer[6:0], 1'b 0};
 | 
				
			||||||
 | 
											next_count = count - |count;
 | 
				
			||||||
 | 
										end else begin
 | 
				
			||||||
 | 
											next_ibuffer = {ibuffer[6:0], flash_io1_di};
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										next_fetch = (next_count == 0);
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									3'b 01?: begin
 | 
				
			||||||
 | 
										flash_io0_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io1_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io2_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io3_oe = !xfer_rd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										flash_io0_do = obuffer[4];
 | 
				
			||||||
 | 
										flash_io1_do = obuffer[5];
 | 
				
			||||||
 | 
										flash_io2_do = obuffer[6];
 | 
				
			||||||
 | 
										flash_io3_do = obuffer[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (flash_clk) begin
 | 
				
			||||||
 | 
											next_obuffer = {obuffer[3:0], 4'b 0000};
 | 
				
			||||||
 | 
											next_count = count - {|count, 2'b00};
 | 
				
			||||||
 | 
										end else begin
 | 
				
			||||||
 | 
											next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										next_fetch = (next_count == 0);
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									3'b 11?: begin
 | 
				
			||||||
 | 
										flash_io0_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io1_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io2_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io3_oe = !xfer_rd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										flash_io0_do = obuffer[4];
 | 
				
			||||||
 | 
										flash_io1_do = obuffer[5];
 | 
				
			||||||
 | 
										flash_io2_do = obuffer[6];
 | 
				
			||||||
 | 
										flash_io3_do = obuffer[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										next_obuffer = {obuffer[3:0], 4'b 0000};
 | 
				
			||||||
 | 
										next_ibuffer = {ibuffer[3:0], flash_io3_di, flash_io2_di, flash_io1_di, flash_io0_di};
 | 
				
			||||||
 | 
										next_count = count - {|count, 2'b00};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										next_fetch = (next_count == 0);
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
									3'b ??1: begin
 | 
				
			||||||
 | 
										flash_io0_oe = !xfer_rd;
 | 
				
			||||||
 | 
										flash_io1_oe = !xfer_rd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										flash_io0_do = obuffer[6];
 | 
				
			||||||
 | 
										flash_io1_do = obuffer[7];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										if (flash_clk) begin
 | 
				
			||||||
 | 
											next_obuffer = {obuffer[5:0], 2'b 00};
 | 
				
			||||||
 | 
											next_count = count - {|count, 1'b0};
 | 
				
			||||||
 | 
										end else begin
 | 
				
			||||||
 | 
											next_ibuffer = {ibuffer[5:0], flash_io1_di, flash_io0_di};
 | 
				
			||||||
 | 
										end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										next_fetch = (next_count == 0);
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
								endcase
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						always @(posedge clk) begin
 | 
				
			||||||
 | 
							if (!resetn) begin
 | 
				
			||||||
 | 
								fetch <= 1;
 | 
				
			||||||
 | 
								last_fetch <= 1;
 | 
				
			||||||
 | 
								flash_csb <= 1;
 | 
				
			||||||
 | 
								flash_clk <= 0;
 | 
				
			||||||
 | 
								count <= 0;
 | 
				
			||||||
 | 
								dummy_count <= 0;
 | 
				
			||||||
 | 
								xfer_tag <= 0;
 | 
				
			||||||
 | 
								xfer_cont <= 0;
 | 
				
			||||||
 | 
								xfer_dspi <= 0;
 | 
				
			||||||
 | 
								xfer_qspi <= 0;
 | 
				
			||||||
 | 
								xfer_ddr <= 0;
 | 
				
			||||||
 | 
								xfer_rd <= 0;
 | 
				
			||||||
 | 
							end else begin
 | 
				
			||||||
 | 
								fetch <= next_fetch;
 | 
				
			||||||
 | 
								last_fetch <= xfer_ddr ? fetch : 1;
 | 
				
			||||||
 | 
								if (dummy_count) begin
 | 
				
			||||||
 | 
									flash_clk <= !flash_clk && !flash_csb;
 | 
				
			||||||
 | 
									dummy_count <= dummy_count - flash_clk;
 | 
				
			||||||
 | 
								end else
 | 
				
			||||||
 | 
								if (count) begin
 | 
				
			||||||
 | 
									flash_clk <= !flash_clk && !flash_csb;
 | 
				
			||||||
 | 
									obuffer <= next_obuffer;
 | 
				
			||||||
 | 
									ibuffer <= next_ibuffer;
 | 
				
			||||||
 | 
									count <= next_count;
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								if (din_valid && din_ready) begin
 | 
				
			||||||
 | 
									flash_csb <= 0;
 | 
				
			||||||
 | 
									flash_clk <= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									count <= 8;
 | 
				
			||||||
 | 
									dummy_count <= din_rd ? din_data : 0;
 | 
				
			||||||
 | 
									obuffer <= din_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									xfer_tag <= din_tag;
 | 
				
			||||||
 | 
									xfer_cont <= din_cont;
 | 
				
			||||||
 | 
									xfer_dspi <= din_dspi;
 | 
				
			||||||
 | 
									xfer_qspi <= din_qspi;
 | 
				
			||||||
 | 
									xfer_ddr <= din_ddr;
 | 
				
			||||||
 | 
									xfer_rd <= din_rd;
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					endmodule
 | 
				
			||||||
							
								
								
									
										131
									
								
								sw/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								sw/Makefile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,131 @@
 | 
				
			|||||||
 | 
					GIT_VERSION := $(shell git describe --tags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# There is no 64-bit gcc on Raspberry Pi, so use the 32-bit version
 | 
				
			||||||
 | 
					ifneq (,$(wildcard /etc/rpi-issue))
 | 
				
			||||||
 | 
					TRGT       ?= riscv32-unknown-elf-
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					TRGT       ?= riscv64-unknown-elf-
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CC         := $(TRGT)gcc
 | 
				
			||||||
 | 
					CXX        := $(TRGT)g++
 | 
				
			||||||
 | 
					OBJCOPY    := $(TRGT)objcopy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RM         := rm -rf
 | 
				
			||||||
 | 
					COPY       := cp -a
 | 
				
			||||||
 | 
					PATH_SEP   := /
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(OS),Windows_NT)
 | 
				
			||||||
 | 
					COPY       := copy
 | 
				
			||||||
 | 
					RM         := del
 | 
				
			||||||
 | 
					PATH_SEP   := \\
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ifeq ($(LITEX),1)
 | 
				
			||||||
 | 
					BASE_DIR   := ../../../../sw
 | 
				
			||||||
 | 
					LDSCRIPT   := $(BASE_DIR)/ld/linker.ld
 | 
				
			||||||
 | 
					LD_DIR     := ../include/generated
 | 
				
			||||||
 | 
					ADD_CFLAGS := -I../include -I$(BASE_DIR)/include
 | 
				
			||||||
 | 
					ADD_LFLAGS := 
 | 
				
			||||||
 | 
					PACKAGE    := bios
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
					BASE_DIR   := .
 | 
				
			||||||
 | 
					LD_DIR     := $(BASE_DIR)/ld
 | 
				
			||||||
 | 
					LDSCRIPT   := $(BASE_DIR)/ld/linker.ld
 | 
				
			||||||
 | 
					ADD_CFLAGS := -I$(BASE_DIR)/include
 | 
				
			||||||
 | 
					ADD_LFLAGS := 
 | 
				
			||||||
 | 
					PACKAGE    := factory-test
 | 
				
			||||||
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LDSCRIPTS  := $(LDSCRIPT) $(LD_DIR)/output_format.ld $(LD_DIR)/regions.ld
 | 
				
			||||||
 | 
					SRC_DIR    := $(BASE_DIR)/src
 | 
				
			||||||
 | 
					THIRD_PARTY := $(BASE_DIR)/third_party
 | 
				
			||||||
 | 
					DBG_CFLAGS := -ggdb -g -DDEBUG -Wall
 | 
				
			||||||
 | 
					DBG_LFLAGS := -ggdb -g -Wall
 | 
				
			||||||
 | 
					CFLAGS     := $(ADD_CFLAGS) \
 | 
				
			||||||
 | 
								  -D__vexriscv__ -march=rv32i  -mabi=ilp32 \
 | 
				
			||||||
 | 
								  -Wall -Wextra \
 | 
				
			||||||
 | 
								  -flto \
 | 
				
			||||||
 | 
								  -ffunction-sections -fdata-sections -fno-common \
 | 
				
			||||||
 | 
								  -fomit-frame-pointer -Os \
 | 
				
			||||||
 | 
								  -march=rv32i \
 | 
				
			||||||
 | 
								  -DGIT_VERSION=u\"$(GIT_VERSION)\" -std=gnu11
 | 
				
			||||||
 | 
					CXXFLAGS   := $(CFLAGS) -std=c++11 -fno-rtti -fno-exceptions
 | 
				
			||||||
 | 
					LFLAGS     := $(CFLAGS) $(ADD_LFLAGS) -L$(LD_DIR) \
 | 
				
			||||||
 | 
								  -nostartfiles \
 | 
				
			||||||
 | 
								  -nostdlib \
 | 
				
			||||||
 | 
								  -Wl,--gc-sections \
 | 
				
			||||||
 | 
								  -Wl,--no-warn-mismatch \
 | 
				
			||||||
 | 
								  -Wl,--script=$(LDSCRIPT) \
 | 
				
			||||||
 | 
								  -Wl,--build-id=none
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					OBJ_DIR    := .obj
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CSOURCES   := $(wildcard $(SRC_DIR)/*.c)
 | 
				
			||||||
 | 
					CPPSOURCES := $(wildcard $(SRC_DIR)/*.cpp)
 | 
				
			||||||
 | 
					ASOURCES   := $(wildcard $(SRC_DIR)/*.S)
 | 
				
			||||||
 | 
					COBJS      := $(addprefix $(OBJ_DIR)/, $(notdir $(CSOURCES:.c=.o)))
 | 
				
			||||||
 | 
					CXXOBJS    := $(addprefix $(OBJ_DIR)/, $(notdir $(CPPSOURCES:.cpp=.o)))
 | 
				
			||||||
 | 
					AOBJS      := $(addprefix $(OBJ_DIR)/, $(notdir $(ASOURCES:.S=.o)))
 | 
				
			||||||
 | 
					OBJECTS    := $(COBJS) $(CXXOBJS) $(AOBJS)
 | 
				
			||||||
 | 
					VPATH      := $(SRC_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					QUIET      := @
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ALL        := all
 | 
				
			||||||
 | 
					TARGET     := $(PACKAGE).elf
 | 
				
			||||||
 | 
					CLEAN      := clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(ALL): $(TARGET) $(PACKAGE).bin $(PACKAGE).ihex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(OBJECTS): | $(OBJ_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(TARGET): $(OBJECTS) $(LDSCRIPTS)
 | 
				
			||||||
 | 
						$(QUIET) echo "  LD       $@"
 | 
				
			||||||
 | 
						$(QUIET) $(CC) $(OBJECTS) $(LFLAGS) -o $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(PACKAGE).bin: $(TARGET)
 | 
				
			||||||
 | 
						$(QUIET) echo "  OBJCOPY  $@"
 | 
				
			||||||
 | 
						$(QUIET) $(OBJCOPY) -O binary $(TARGET) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(PACKAGE).dfu: $(TARGET)
 | 
				
			||||||
 | 
						$(QUIET) echo "  DFU      $@"
 | 
				
			||||||
 | 
						$(QUIET) $(COPY) $(PACKAGE).bin $@
 | 
				
			||||||
 | 
						$(QUIET) dfu-suffix -v 1209 -p 70b1 -a $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(PACKAGE).ihex: $(TARGET)
 | 
				
			||||||
 | 
						$(QUIET) echo "  IHEX     $(PACKAGE).ihex"
 | 
				
			||||||
 | 
						$(QUIET) $(OBJCOPY) -O ihex $(TARGET) $@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(DEBUG): CFLAGS += $(DBG_CFLAGS)
 | 
				
			||||||
 | 
					$(DEBUG): LFLAGS += $(DBG_LFLAGS)
 | 
				
			||||||
 | 
					CFLAGS += $(DBG_CFLAGS)
 | 
				
			||||||
 | 
					LFLAGS += $(DBG_LFLAGS)
 | 
				
			||||||
 | 
					$(DEBUG): $(TARGET)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(OBJ_DIR):
 | 
				
			||||||
 | 
						$(QUIET) mkdir $(OBJ_DIR)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(COBJS) : $(OBJ_DIR)/%.o : %.c $(BASE_DIR)/Makefile
 | 
				
			||||||
 | 
						$(QUIET) echo "  CC       $<	$(notdir $@)"
 | 
				
			||||||
 | 
						$(QUIET) $(CC) -c $< $(CFLAGS) -o $@ -MMD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(OBJ_DIR)/%.o: %.cpp
 | 
				
			||||||
 | 
						$(QUIET) echo "  CXX      $<	$(notdir $@)"
 | 
				
			||||||
 | 
						$(QUIET) $(CXX) -c $< $(CXXFLAGS) -o $@ -MMD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$(OBJ_DIR)/%.o: %.S
 | 
				
			||||||
 | 
						$(QUIET) echo "  AS       $<	$(notdir $@)"
 | 
				
			||||||
 | 
						$(QUIET) $(CC) -x assembler-with-cpp -c $< $(CFLAGS) -o $@ -MMD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.PHONY: clean
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					clean:
 | 
				
			||||||
 | 
						$(QUIET) echo "  RM      $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))"
 | 
				
			||||||
 | 
						-$(QUIET) $(RM) $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))
 | 
				
			||||||
 | 
						$(QUIET) echo "  RM      $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.d))"
 | 
				
			||||||
 | 
						-$(QUIET) $(RM) $(subst /,$(PATH_SEP),$(wildcard $(OBJ_DIR)/*.o))
 | 
				
			||||||
 | 
						$(QUIET) echo "  RM      $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu"
 | 
				
			||||||
 | 
						-$(QUIET) $(RM) $(TARGET) $(PACKAGE).bin $(PACKAGE).symbol $(PACKAGE).ihex $(PACKAGE).dfu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					include $(wildcard $(OBJ_DIR)/*.d)
 | 
				
			||||||
							
								
								
									
										903
									
								
								sw/include/fomu/csr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										903
									
								
								sw/include/fomu/csr.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,903 @@
 | 
				
			|||||||
 | 
					#ifndef __GENERATED_CSR_H
 | 
				
			||||||
 | 
					#define __GENERATED_CSR_H
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#ifdef CSR_ACCESSORS_DEFINED
 | 
				
			||||||
 | 
					extern void csr_writeb(uint8_t value, uint32_t addr);
 | 
				
			||||||
 | 
					extern uint8_t csr_readb(uint32_t addr);
 | 
				
			||||||
 | 
					extern void csr_writew(uint16_t value, uint32_t addr);
 | 
				
			||||||
 | 
					extern uint16_t csr_readw(uint32_t addr);
 | 
				
			||||||
 | 
					extern void csr_writel(uint32_t value, uint32_t addr);
 | 
				
			||||||
 | 
					extern uint32_t csr_readl(uint32_t addr);
 | 
				
			||||||
 | 
					#else /* ! CSR_ACCESSORS_DEFINED */
 | 
				
			||||||
 | 
					static inline void csr_writeb(uint8_t value, uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*((volatile uint8_t *)addr) = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint8_t csr_readb(uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(volatile uint8_t *)addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void csr_writew(uint16_t value, uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*((volatile uint16_t *)addr) = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint16_t csr_readw(uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(volatile uint16_t *)addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void csr_writel(uint32_t value, uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						*((volatile uint32_t *)addr) = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline uint32_t csr_readl(uint32_t addr)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return *(volatile uint32_t *)addr;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif /* ! CSR_ACCESSORS_DEFINED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* ctrl */
 | 
				
			||||||
 | 
					#define CSR_CTRL_BASE 0xe0000000
 | 
				
			||||||
 | 
					#define CSR_CTRL_RESET_ADDR 0xe0000000
 | 
				
			||||||
 | 
					#define CSR_CTRL_RESET_SIZE 1
 | 
				
			||||||
 | 
						static inline unsigned char
 | 
				
			||||||
 | 
						ctrl_reset_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0000000);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void ctrl_reset_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0000000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_CTRL_SCRATCH_ADDR 0xe0000004
 | 
				
			||||||
 | 
					#define CSR_CTRL_SCRATCH_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int ctrl_scratch_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0000004);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0000008);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000000c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0000010);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void ctrl_scratch_write(unsigned int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value >> 24, 0xe0000004);
 | 
				
			||||||
 | 
						csr_writel(value >> 16, 0xe0000008);
 | 
				
			||||||
 | 
						csr_writel(value >> 8, 0xe000000c);
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0000010);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_CTRL_BUS_ERRORS_ADDR 0xe0000014
 | 
				
			||||||
 | 
					#define CSR_CTRL_BUS_ERRORS_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int ctrl_bus_errors_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0000014);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0000018);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000001c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0000020);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* picorvspi */
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_BASE 0xe0005000
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG1_ADDR 0xe0005000
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG1_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_cfg1_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005000);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void picorvspi_cfg1_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0005000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG2_ADDR 0xe0005004
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG2_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_cfg2_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005004);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void picorvspi_cfg2_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0005004);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG3_ADDR 0xe0005008
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG3_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_cfg3_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005008);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void picorvspi_cfg3_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0005008);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG4_ADDR 0xe000500c
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_CFG4_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_cfg4_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000500c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void picorvspi_cfg4_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000500c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT1_ADDR 0xe0005010
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT1_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_stat1_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005010);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT2_ADDR 0xe0005014
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT2_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_stat2_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005014);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT3_ADDR 0xe0005018
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT3_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_stat3_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005018);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT4_ADDR 0xe000501c
 | 
				
			||||||
 | 
					#define CSR_PICORVSPI_STAT4_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char picorvspi_stat4_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000501c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* reboot */
 | 
				
			||||||
 | 
					#define CSR_REBOOT_BASE 0xe0006000
 | 
				
			||||||
 | 
					#define CSR_REBOOT_CTRL_ADDR 0xe0006000
 | 
				
			||||||
 | 
					#define CSR_REBOOT_CTRL_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char reboot_ctrl_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0006000);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void reboot_ctrl_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0006000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_REBOOT_ADDR_ADDR 0xe0006004
 | 
				
			||||||
 | 
					#define CSR_REBOOT_ADDR_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int reboot_addr_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0006004);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0006008);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000600c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0006010);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void reboot_addr_write(unsigned int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value >> 24, 0xe0006004);
 | 
				
			||||||
 | 
						csr_writel(value >> 16, 0xe0006008);
 | 
				
			||||||
 | 
						csr_writel(value >> 8, 0xe000600c);
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0006010);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* rgb */
 | 
				
			||||||
 | 
					#define CSR_RGB_BASE 0xe0006800
 | 
				
			||||||
 | 
					#define CSR_RGB_DAT_ADDR 0xe0006800
 | 
				
			||||||
 | 
					#define CSR_RGB_DAT_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char rgb_dat_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0006800);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void rgb_dat_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0006800);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_RGB_ADDR_ADDR 0xe0006804
 | 
				
			||||||
 | 
					#define CSR_RGB_ADDR_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char rgb_addr_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0006804);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void rgb_addr_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0006804);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_RGB_CTRL_ADDR 0xe0006808
 | 
				
			||||||
 | 
					#define CSR_RGB_CTRL_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char rgb_ctrl_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0006808);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void rgb_ctrl_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0006808);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* timer0 */
 | 
				
			||||||
 | 
					#define CSR_TIMER0_BASE 0xe0002800
 | 
				
			||||||
 | 
					#define CSR_TIMER0_LOAD_ADDR 0xe0002800
 | 
				
			||||||
 | 
					#define CSR_TIMER0_LOAD_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int timer0_load_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0002800);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002804);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002808);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000280c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_load_write(unsigned int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value >> 24, 0xe0002800);
 | 
				
			||||||
 | 
						csr_writel(value >> 16, 0xe0002804);
 | 
				
			||||||
 | 
						csr_writel(value >> 8, 0xe0002808);
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000280c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_RELOAD_ADDR 0xe0002810
 | 
				
			||||||
 | 
					#define CSR_TIMER0_RELOAD_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int timer0_reload_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0002810);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002814);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002818);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000281c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_reload_write(unsigned int value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value >> 24, 0xe0002810);
 | 
				
			||||||
 | 
						csr_writel(value >> 16, 0xe0002814);
 | 
				
			||||||
 | 
						csr_writel(value >> 8, 0xe0002818);
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000281c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EN_ADDR 0xe0002820
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EN_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char timer0_en_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0002820);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_en_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0002820);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_UPDATE_VALUE_ADDR 0xe0002824
 | 
				
			||||||
 | 
					#define CSR_TIMER0_UPDATE_VALUE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char timer0_update_value_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0002824);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_update_value_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0002824);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_VALUE_ADDR 0xe0002828
 | 
				
			||||||
 | 
					#define CSR_TIMER0_VALUE_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int timer0_value_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe0002828);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe000282c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002830);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0002834);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_STATUS_ADDR 0xe0002838
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char timer0_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0002838);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0002838);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_PENDING_ADDR 0xe000283c
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char timer0_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000283c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000283c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_ENABLE_ADDR 0xe0002840
 | 
				
			||||||
 | 
					#define CSR_TIMER0_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char timer0_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0002840);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void timer0_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0002840);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* touch */
 | 
				
			||||||
 | 
					#define CSR_TOUCH_BASE 0xe0005800
 | 
				
			||||||
 | 
					#define CSR_TOUCH_O_ADDR 0xe0005800
 | 
				
			||||||
 | 
					#define CSR_TOUCH_O_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char touch_o_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005800);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void touch_o_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0005800);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TOUCH_OE_ADDR 0xe0005804
 | 
				
			||||||
 | 
					#define CSR_TOUCH_OE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char touch_oe_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005804);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void touch_oe_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0005804);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_TOUCH_I_ADDR 0xe0005808
 | 
				
			||||||
 | 
					#define CSR_TOUCH_I_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char touch_i_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0005808);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* usb */
 | 
				
			||||||
 | 
					#define CSR_USB_BASE 0xe0004800
 | 
				
			||||||
 | 
					#define CSR_USB_PULLUP_OUT_ADDR 0xe0004800
 | 
				
			||||||
 | 
					#define CSR_USB_PULLUP_OUT_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_pullup_out_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004800);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_pullup_out_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004800);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_STATUS_ADDR 0xe0004804
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004804);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004804);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_PENDING_ADDR 0xe0004808
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004808);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004808);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_ENABLE_ADDR 0xe000480c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000480c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000480c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_LAST_TOK_ADDR 0xe0004810
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_LAST_TOK_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_last_tok_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004810);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_RESPOND_ADDR 0xe0004814
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_RESPOND_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_respond_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004814);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_respond_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004814);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_DTB_ADDR 0xe0004818
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_DTB_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_dtb_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004818);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_dtb_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004818);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_OBUF_HEAD_ADDR 0xe000481c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_OBUF_HEAD_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_obuf_head_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000481c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_out_obuf_head_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000481c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_OBUF_EMPTY_ADDR 0xe0004820
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_OUT_OBUF_EMPTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_out_obuf_empty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004820);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_STATUS_ADDR 0xe0004824
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004824);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004824);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_PENDING_ADDR 0xe0004828
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004828);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004828);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_ENABLE_ADDR 0xe000482c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000482c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000482c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_LAST_TOK_ADDR 0xe0004830
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_LAST_TOK_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_last_tok_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004830);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_RESPOND_ADDR 0xe0004834
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_RESPOND_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_respond_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004834);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_respond_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004834);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_DTB_ADDR 0xe0004838
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_DTB_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_dtb_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004838);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_dtb_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004838);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_IBUF_HEAD_ADDR 0xe000483c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_IBUF_HEAD_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_ibuf_head_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000483c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_0_in_ibuf_head_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000483c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_IBUF_EMPTY_ADDR 0xe0004840
 | 
				
			||||||
 | 
					#define CSR_USB_EP_0_IN_IBUF_EMPTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_0_in_ibuf_empty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004840);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_STATUS_ADDR 0xe0004844
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004844);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004844);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_PENDING_ADDR 0xe0004848
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004848);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004848);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_ENABLE_ADDR 0xe000484c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000484c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000484c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_LAST_TOK_ADDR 0xe0004850
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_LAST_TOK_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_last_tok_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004850);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_RESPOND_ADDR 0xe0004854
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_RESPOND_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_respond_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004854);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_respond_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004854);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_DTB_ADDR 0xe0004858
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_DTB_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_dtb_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004858);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_dtb_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004858);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_IBUF_HEAD_ADDR 0xe000485c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_IBUF_HEAD_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_ibuf_head_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000485c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_1_in_ibuf_head_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000485c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_IBUF_EMPTY_ADDR 0xe0004860
 | 
				
			||||||
 | 
					#define CSR_USB_EP_1_IN_IBUF_EMPTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_1_in_ibuf_empty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004860);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_STATUS_ADDR 0xe0004864
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004864);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004864);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_PENDING_ADDR 0xe0004868
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004868);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004868);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_ENABLE_ADDR 0xe000486c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000486c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000486c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_LAST_TOK_ADDR 0xe0004870
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_LAST_TOK_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_last_tok_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004870);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_RESPOND_ADDR 0xe0004874
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_RESPOND_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_respond_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004874);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_respond_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004874);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_DTB_ADDR 0xe0004878
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_DTB_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_dtb_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004878);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_dtb_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004878);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_OBUF_HEAD_ADDR 0xe000487c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_OBUF_HEAD_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_obuf_head_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000487c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_out_obuf_head_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000487c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_OBUF_EMPTY_ADDR 0xe0004880
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_OUT_OBUF_EMPTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_out_obuf_empty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004880);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_STATUS_ADDR 0xe0004884
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_STATUS_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_ev_status_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004884);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_ev_status_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004884);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_PENDING_ADDR 0xe0004888
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_PENDING_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_ev_pending_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004888);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_ev_pending_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004888);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_ENABLE_ADDR 0xe000488c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_EV_ENABLE_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_ev_enable_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000488c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_ev_enable_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000488c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_LAST_TOK_ADDR 0xe0004890
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_LAST_TOK_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_last_tok_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004890);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_RESPOND_ADDR 0xe0004894
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_RESPOND_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_respond_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004894);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_respond_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004894);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_DTB_ADDR 0xe0004898
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_DTB_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_dtb_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0004898);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_dtb_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe0004898);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_IBUF_HEAD_ADDR 0xe000489c
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_IBUF_HEAD_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_ibuf_head_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe000489c);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static inline void usb_ep_2_in_ibuf_head_write(unsigned char value)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						csr_writel(value, 0xe000489c);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_IBUF_EMPTY_ADDR 0xe00048a0
 | 
				
			||||||
 | 
					#define CSR_USB_EP_2_IN_IBUF_EMPTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char usb_ep_2_in_ibuf_empty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe00048a0);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* version */
 | 
				
			||||||
 | 
					#define CSR_VERSION_BASE 0xe0007000
 | 
				
			||||||
 | 
					#define CSR_VERSION_MAJOR_ADDR 0xe0007000
 | 
				
			||||||
 | 
					#define CSR_VERSION_MAJOR_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char version_major_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0007000);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_VERSION_MINOR_ADDR 0xe0007004
 | 
				
			||||||
 | 
					#define CSR_VERSION_MINOR_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char version_minor_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0007004);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_VERSION_REVISION_ADDR 0xe0007008
 | 
				
			||||||
 | 
					#define CSR_VERSION_REVISION_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char version_revision_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0007008);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_VERSION_GITREV_ADDR 0xe000700c
 | 
				
			||||||
 | 
					#define CSR_VERSION_GITREV_SIZE 4
 | 
				
			||||||
 | 
					static inline unsigned int version_gitrev_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned int r = csr_readl(0xe000700c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0007010);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0007014);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0007018);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_VERSION_GITEXTRA_ADDR 0xe000701c
 | 
				
			||||||
 | 
					#define CSR_VERSION_GITEXTRA_SIZE 2
 | 
				
			||||||
 | 
					static inline unsigned short int version_gitextra_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned short int r = csr_readl(0xe000701c);
 | 
				
			||||||
 | 
						r <<= 8;
 | 
				
			||||||
 | 
						r |= csr_readl(0xe0007020);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_VERSION_DIRTY_ADDR 0xe0007024
 | 
				
			||||||
 | 
					#define CSR_VERSION_DIRTY_SIZE 1
 | 
				
			||||||
 | 
					static inline unsigned char version_dirty_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned char r = csr_readl(0xe0007024);
 | 
				
			||||||
 | 
						return r;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* constants */
 | 
				
			||||||
 | 
					#define NMI_INTERRUPT 0
 | 
				
			||||||
 | 
					static inline int nmi_interrupt_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define TIMER0_INTERRUPT 1
 | 
				
			||||||
 | 
					static inline int timer0_interrupt_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 1;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define UART_INTERRUPT 2
 | 
				
			||||||
 | 
					static inline int uart_interrupt_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 2;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define USB_INTERRUPT 3
 | 
				
			||||||
 | 
					static inline int usb_interrupt_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 3;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CSR_DATA_WIDTH 8
 | 
				
			||||||
 | 
					static inline int csr_data_width_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define SYSTEM_CLOCK_FREQUENCY 12000000
 | 
				
			||||||
 | 
					static inline int system_clock_frequency_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 12000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CONFIG_CLOCK_FREQUENCY 12000000
 | 
				
			||||||
 | 
					static inline int config_clock_frequency_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 12000000;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CONFIG_CPU_RESET_ADDR 0
 | 
				
			||||||
 | 
					static inline int config_cpu_reset_addr_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CONFIG_CPU_TYPE "VEXRISCV"
 | 
				
			||||||
 | 
					static inline const char *config_cpu_type_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return "VEXRISCV";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CONFIG_CPU_VARIANT "VEXRISCV"
 | 
				
			||||||
 | 
					static inline const char *config_cpu_variant_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return "VEXRISCV";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#define CONFIG_CSR_DATA_WIDTH 8
 | 
				
			||||||
 | 
					static inline int config_csr_data_width_read(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return 8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										16
									
								
								sw/include/fomu/mem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								sw/include/fomu/mem.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#ifndef __GENERATED_MEM_H
 | 
				
			||||||
 | 
					#define __GENERATED_MEM_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define VEXRISCV_DEBUG_BASE 0xf00f0000
 | 
				
			||||||
 | 
					#define VEXRISCV_DEBUG_SIZE 0x00000010
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SRAM_BASE 0x10000000
 | 
				
			||||||
 | 
					#define SRAM_SIZE 0x00020000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define ROM_BASE 0x00000000
 | 
				
			||||||
 | 
					#define ROM_SIZE 0x00002000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SPIFLASH_BASE 0x20000000
 | 
				
			||||||
 | 
					#define SPIFLASH_SIZE 0x00200000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										145
									
								
								sw/include/irq.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								sw/include/irq.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,145 @@
 | 
				
			|||||||
 | 
					#ifndef __IRQ_H
 | 
				
			||||||
 | 
					#define __IRQ_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <riscv.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __picorv32__
 | 
				
			||||||
 | 
					// PicoRV32 has a very limited interrupt support, implemented via custom
 | 
				
			||||||
 | 
					// instructions. It also doesn't have a global interrupt enable/disable, so
 | 
				
			||||||
 | 
					// we have to emulate it via saving and restoring a mask and using 0/~1 as a
 | 
				
			||||||
 | 
					// hardware mask.
 | 
				
			||||||
 | 
					// Due to all this somewhat low-level mess, all of the glue is implemented in
 | 
				
			||||||
 | 
					// the RiscV crt0, and this header is kept as a thin wrapper. Since interrupts
 | 
				
			||||||
 | 
					// managed by this layer, do not call interrupt instructions directly, as the
 | 
				
			||||||
 | 
					// state will go out of sync with the hardware.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Read only.
 | 
				
			||||||
 | 
					extern unsigned int _irq_pending;
 | 
				
			||||||
 | 
					// Read only.
 | 
				
			||||||
 | 
					extern unsigned int _irq_mask;
 | 
				
			||||||
 | 
					// Read only.
 | 
				
			||||||
 | 
					extern unsigned int _irq_enabled;
 | 
				
			||||||
 | 
					extern void _irq_enable(void);
 | 
				
			||||||
 | 
					extern void _irq_disable(void);
 | 
				
			||||||
 | 
					extern void _irq_setmask(unsigned int);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int irq_getie(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined (__lm32__)
 | 
				
			||||||
 | 
						unsigned int ie;
 | 
				
			||||||
 | 
						__asm__ __volatile__("rcsr %0, IE" : "=r" (ie));
 | 
				
			||||||
 | 
						return ie;
 | 
				
			||||||
 | 
					#elif defined (__or1k__)
 | 
				
			||||||
 | 
						return !!(mfspr(SPR_SR) & SPR_SR_IEE);
 | 
				
			||||||
 | 
					#elif defined (__picorv32__)
 | 
				
			||||||
 | 
						return _irq_enabled != 0;
 | 
				
			||||||
 | 
					#elif defined (__vexriscv__)
 | 
				
			||||||
 | 
						return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
 | 
				
			||||||
 | 
					#elif defined (__minerva__)
 | 
				
			||||||
 | 
						return (csrr(mstatus) & CSR_MSTATUS_MIE) != 0;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void irq_setie(unsigned int ie)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined (__lm32__)
 | 
				
			||||||
 | 
						__asm__ __volatile__("wcsr IE, %0" : : "r" (ie));
 | 
				
			||||||
 | 
					#elif defined (__or1k__)
 | 
				
			||||||
 | 
						if (ie & 0x1)
 | 
				
			||||||
 | 
							mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_IEE);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_IEE);
 | 
				
			||||||
 | 
					#elif defined (__picorv32__)
 | 
				
			||||||
 | 
					    if (ie & 0x1)
 | 
				
			||||||
 | 
					        _irq_enable();
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        _irq_disable();
 | 
				
			||||||
 | 
					#elif defined (__vexriscv__)
 | 
				
			||||||
 | 
						if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
 | 
				
			||||||
 | 
					#elif defined (__minerva__)
 | 
				
			||||||
 | 
						if(ie) csrs(mstatus,CSR_MSTATUS_MIE); else csrc(mstatus,CSR_MSTATUS_MIE);
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int irq_getmask(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined (__lm32__)
 | 
				
			||||||
 | 
						unsigned int mask;
 | 
				
			||||||
 | 
						__asm__ __volatile__("rcsr %0, IM" : "=r" (mask));
 | 
				
			||||||
 | 
						return mask;
 | 
				
			||||||
 | 
					#elif defined (__or1k__)
 | 
				
			||||||
 | 
						return mfspr(SPR_PICMR);
 | 
				
			||||||
 | 
					#elif defined (__picorv32__)
 | 
				
			||||||
 | 
					    // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
 | 
				
			||||||
 | 
					    // LiteX sees things.
 | 
				
			||||||
 | 
					    return ~_irq_mask;
 | 
				
			||||||
 | 
					#elif defined (__vexriscv__)
 | 
				
			||||||
 | 
						unsigned int mask;
 | 
				
			||||||
 | 
						asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
 | 
				
			||||||
 | 
						return mask;
 | 
				
			||||||
 | 
					#elif defined (__minerva__)
 | 
				
			||||||
 | 
						unsigned int mask;
 | 
				
			||||||
 | 
						asm volatile ("csrr %0, %1" : "=r"(mask) : "i"(CSR_IRQ_MASK));
 | 
				
			||||||
 | 
						return mask;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline void irq_setmask(unsigned int mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined (__lm32__)
 | 
				
			||||||
 | 
						__asm__ __volatile__("wcsr IM, %0" : : "r" (mask));
 | 
				
			||||||
 | 
					#elif defined (__or1k__)
 | 
				
			||||||
 | 
						mtspr(SPR_PICMR, mask);
 | 
				
			||||||
 | 
					#elif defined (__picorv32__)
 | 
				
			||||||
 | 
					    // PicoRV32 interrupt mask bits are high-disabled. This is the inverse of how
 | 
				
			||||||
 | 
					    // LiteX sees things.
 | 
				
			||||||
 | 
					    _irq_setmask(~mask);
 | 
				
			||||||
 | 
					#elif defined (__vexriscv__)
 | 
				
			||||||
 | 
						asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
 | 
				
			||||||
 | 
					#elif defined (__minerva__)
 | 
				
			||||||
 | 
						asm volatile ("csrw %0, %1" :: "i"(CSR_IRQ_MASK), "r"(mask));
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline unsigned int irq_pending(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#if defined (__lm32__)
 | 
				
			||||||
 | 
						unsigned int pending;
 | 
				
			||||||
 | 
						__asm__ __volatile__("rcsr %0, IP" : "=r" (pending));
 | 
				
			||||||
 | 
						return pending;
 | 
				
			||||||
 | 
					#elif defined (__or1k__)
 | 
				
			||||||
 | 
						return mfspr(SPR_PICSR);
 | 
				
			||||||
 | 
					#elif defined (__picorv32__)
 | 
				
			||||||
 | 
						return _irq_pending;
 | 
				
			||||||
 | 
					#elif defined (__vexriscv__)
 | 
				
			||||||
 | 
						unsigned int pending;
 | 
				
			||||||
 | 
						asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
 | 
				
			||||||
 | 
						return pending;
 | 
				
			||||||
 | 
					#elif defined (__minerva__)
 | 
				
			||||||
 | 
						unsigned int pending;
 | 
				
			||||||
 | 
						asm volatile ("csrr %0, %1" : "=r"(pending) : "i"(CSR_IRQ_PENDING));
 | 
				
			||||||
 | 
						return pending;
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#error Unsupported architecture
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __IRQ_H */
 | 
				
			||||||
							
								
								
									
										10
									
								
								sw/include/rgb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								sw/include/rgb.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					#ifndef _RGB_H_
 | 
				
			||||||
 | 
					#define _RGB_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_init(void);
 | 
				
			||||||
 | 
					void rgb_mode_idle(void);
 | 
				
			||||||
 | 
					void rgb_mode_done(void);
 | 
				
			||||||
 | 
					void rgb_mode_writing(void);
 | 
				
			||||||
 | 
					void rgb_mode_error(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* _RGB_H_ */
 | 
				
			||||||
							
								
								
									
										54
									
								
								sw/include/riscv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								sw/include/riscv.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					#ifndef RISCV_DEFS_H__
 | 
				
			||||||
 | 
					#define RISCV_DEFS_H__
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <fomu/csr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSR_MSTATUS_MIE 0x8
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSR_IRQ_MASK 0xBC0
 | 
				
			||||||
 | 
					#define CSR_IRQ_PENDING 0xFC0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define CSR_DCACHE_INFO 0xCC0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void flush_cpu_icache(void);
 | 
				
			||||||
 | 
					void flush_cpu_dcache(void);
 | 
				
			||||||
 | 
					void flush_l2_cache(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define csrr(reg) ({ unsigned long __tmp; \
 | 
				
			||||||
 | 
					  asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
 | 
				
			||||||
 | 
					  __tmp; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define csrw(reg, val) ({ \
 | 
				
			||||||
 | 
					  if (__builtin_constant_p(val) && (unsigned long)(val) < 32) \
 | 
				
			||||||
 | 
						asm volatile ("csrw " #reg ", %0" :: "i"(val)); \
 | 
				
			||||||
 | 
					  else \
 | 
				
			||||||
 | 
						asm volatile ("csrw " #reg ", %0" :: "r"(val)); })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define csrs(reg, bit) ({ \
 | 
				
			||||||
 | 
					  if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
 | 
				
			||||||
 | 
						asm volatile ("csrrs x0, " #reg ", %0" :: "i"(bit)); \
 | 
				
			||||||
 | 
					  else \
 | 
				
			||||||
 | 
						asm volatile ("csrrs x0, " #reg ", %0" :: "r"(bit)); })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define csrc(reg, bit) ({ \
 | 
				
			||||||
 | 
					  if (__builtin_constant_p(bit) && (unsigned long)(bit) < 32) \
 | 
				
			||||||
 | 
						asm volatile ("csrrc x0, " #reg ", %0" :: "i"(bit)); \
 | 
				
			||||||
 | 
					  else \
 | 
				
			||||||
 | 
						asm volatile ("csrrc x0, " #reg ", %0" :: "r"(bit)); })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((noreturn)) void reboot(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((noreturn)) static inline void warmboot_to_image(uint8_t image_index) {
 | 
				
			||||||
 | 
						reboot_ctrl_write(0xac | (image_index & 3) << 0);
 | 
				
			||||||
 | 
						while (1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif	/* RISCV_DEFS_H__ */
 | 
				
			||||||
							
								
								
									
										94
									
								
								sw/include/spi.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								sw/include/spi.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					#ifndef BB_SPI_H_
 | 
				
			||||||
 | 
					#define BB_SPI_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum spi_state {
 | 
				
			||||||
 | 
						SS_UNCONFIGURED = 0,
 | 
				
			||||||
 | 
						SS_SINGLE,
 | 
				
			||||||
 | 
						SS_DUAL_RX,
 | 
				
			||||||
 | 
						SS_DUAL_TX,
 | 
				
			||||||
 | 
						SS_QUAD_RX,
 | 
				
			||||||
 | 
						SS_QUAD_TX,
 | 
				
			||||||
 | 
						SS_HARDWARE,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum spi_type {
 | 
				
			||||||
 | 
						ST_UNCONFIGURED,
 | 
				
			||||||
 | 
						ST_SINGLE,
 | 
				
			||||||
 | 
						ST_DUAL,
 | 
				
			||||||
 | 
						ST_QUAD,
 | 
				
			||||||
 | 
						ST_QPI,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum spi_pin {
 | 
				
			||||||
 | 
						SP_MOSI,
 | 
				
			||||||
 | 
						SP_MISO,
 | 
				
			||||||
 | 
						SP_HOLD,
 | 
				
			||||||
 | 
						SP_WP,
 | 
				
			||||||
 | 
						SP_CS,
 | 
				
			||||||
 | 
						SP_CLK,
 | 
				
			||||||
 | 
						SP_D0,
 | 
				
			||||||
 | 
						SP_D1,
 | 
				
			||||||
 | 
						SP_D2,
 | 
				
			||||||
 | 
						SP_D3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct spi_id {
 | 
				
			||||||
 | 
						uint8_t manufacturer_id;	// Result from 0x90
 | 
				
			||||||
 | 
						uint8_t device_id;		// Result from 0x90
 | 
				
			||||||
 | 
						uint8_t _manufacturer_id;	// Result from 0x9f
 | 
				
			||||||
 | 
						uint8_t memory_type;		// Result from 0x9f
 | 
				
			||||||
 | 
						uint8_t memory_size;		// Result from 0x9f
 | 
				
			||||||
 | 
						uint8_t signature;		// Result from 0xab
 | 
				
			||||||
 | 
						uint8_t serial[4];		// Result from 0x4b
 | 
				
			||||||
 | 
						int bytes;			// -1 if unknown
 | 
				
			||||||
 | 
						const char *manufacturer;
 | 
				
			||||||
 | 
						const char *model;
 | 
				
			||||||
 | 
						const char *capacity;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ff_spi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiPause(struct ff_spi *spi);
 | 
				
			||||||
 | 
					void spiBegin(struct ff_spi *spi);
 | 
				
			||||||
 | 
					void spiEnd(struct ff_spi *spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//void spiSingleTx(struct ff_spi *spi, uint8_t out);
 | 
				
			||||||
 | 
					//uint8_t spiSingleRx(struct ff_spi *spi);
 | 
				
			||||||
 | 
					//void spiDualTx(struct ff_spi *spi, uint8_t out);
 | 
				
			||||||
 | 
					//void spiQuadTx(struct ff_spi *spi, uint8_t out);
 | 
				
			||||||
 | 
					void spiCommand(struct ff_spi *spi, uint8_t cmd);
 | 
				
			||||||
 | 
					//uint8_t spiDualRx(struct ff_spi *spi);
 | 
				
			||||||
 | 
					//uint8_t spiQuadRx(struct ff_spi *spi);
 | 
				
			||||||
 | 
					int spiTx(struct ff_spi *spi, uint8_t word);
 | 
				
			||||||
 | 
					uint8_t spiRx(struct ff_spi *spi);
 | 
				
			||||||
 | 
					uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr);
 | 
				
			||||||
 | 
					void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val);
 | 
				
			||||||
 | 
					void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]);
 | 
				
			||||||
 | 
					void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]);
 | 
				
			||||||
 | 
					int spiSetType(struct ff_spi *spi, enum spi_type type);
 | 
				
			||||||
 | 
					int spiRead(struct ff_spi *spi, uint32_t addr, uint8_t *data, unsigned int count);
 | 
				
			||||||
 | 
					int spiIsBusy(struct ff_spi *spi);
 | 
				
			||||||
 | 
					int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr);
 | 
				
			||||||
 | 
					int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr);
 | 
				
			||||||
 | 
					int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *data, unsigned int count);
 | 
				
			||||||
 | 
					void spiEnableQuad(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct spi_id spiId(struct ff_spi *spi);
 | 
				
			||||||
 | 
					void spiOverrideSize(struct ff_spi *spi, uint32_t new_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//int spi_wait_for_not_busy(struct ff_spi *spi);
 | 
				
			||||||
 | 
					int spiWrite(struct ff_spi *spi, uint32_t addr, const uint8_t *data, unsigned int count);
 | 
				
			||||||
 | 
					uint8_t spiReset(struct ff_spi *spi);
 | 
				
			||||||
 | 
					int spiInit(struct ff_spi *spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiHold(struct ff_spi *spi);
 | 
				
			||||||
 | 
					void spiUnhold(struct ff_spi *spi);
 | 
				
			||||||
 | 
					void spiSwapTxRx(struct ff_spi *spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ff_spi *spiAlloc(void);
 | 
				
			||||||
 | 
					void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val);
 | 
				
			||||||
 | 
					void spiFree(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* BB_SPI_H_ */
 | 
				
			||||||
							
								
								
									
										16
									
								
								sw/include/time.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								sw/include/time.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#ifndef __TIME_H
 | 
				
			||||||
 | 
					#define __TIME_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void time_init(void);
 | 
				
			||||||
 | 
					int elapsed(int *last_event, int period);
 | 
				
			||||||
 | 
					void msleep(int ms);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* __TIME_H */
 | 
				
			||||||
							
								
								
									
										162
									
								
								sw/include/usb-cdc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								sw/include/usb-cdc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,162 @@
 | 
				
			|||||||
 | 
					/** @defgroup usb_cdc_defines USB CDC Type Definitions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@brief <b>Defined Constants and Types for the USB CDC Type Definitions</b>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@ingroup USB_defines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@version 1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@author @htmlonly © @endhtmlonly 2010
 | 
				
			||||||
 | 
					Gareth McMullin <gareth@blacksphere.co.nz>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@date 10 March 2013
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					LGPL License Terms @ref lgpl_license
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * This file is part of the libopencm3 project.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU Lesser General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This library is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU Lesser General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU Lesser General Public License
 | 
				
			||||||
 | 
					 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**@{*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef __CDC_H
 | 
				
			||||||
 | 
					#define __CDC_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Definitions of Communications Device Class from
 | 
				
			||||||
 | 
					 * "Universal Serial Bus Class Definitions for Communications Devices
 | 
				
			||||||
 | 
					 * Revision 1.2"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 2: Communications Device Class Code */
 | 
				
			||||||
 | 
					#define USB_CLASS_CDC			0x02
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 4: Class Subclass Code */
 | 
				
			||||||
 | 
					#define USB_CDC_SUBCLASS_DLCM		0x01
 | 
				
			||||||
 | 
					#define USB_CDC_SUBCLASS_ACM		0x02
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 5 Communications Interface Class Control Protocol Codes */
 | 
				
			||||||
 | 
					#define USB_CDC_PROTOCOL_NONE		0x00
 | 
				
			||||||
 | 
					#define USB_CDC_PROTOCOL_AT		0x01
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 6: Data Interface Class Code */
 | 
				
			||||||
 | 
					#define USB_CLASS_DATA			0x0A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 12: Type Values for the bDescriptorType Field */
 | 
				
			||||||
 | 
					#define CS_INTERFACE			0x24
 | 
				
			||||||
 | 
					#define CS_ENDPOINT			0x25
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 13: bDescriptor SubType in Communications Class Functional
 | 
				
			||||||
 | 
					 * Descriptors */
 | 
				
			||||||
 | 
					#define USB_CDC_TYPE_HEADER		0x00
 | 
				
			||||||
 | 
					#define USB_CDC_TYPE_CALL_MANAGEMENT	0x01
 | 
				
			||||||
 | 
					#define USB_CDC_TYPE_ACM		0x02
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					#define USB_CDC_TYPE_UNION		0x06
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 15: Class-Specific Descriptor Header Format */
 | 
				
			||||||
 | 
					struct usb_cdc_header_descriptor {
 | 
				
			||||||
 | 
						uint8_t bFunctionLength;
 | 
				
			||||||
 | 
						uint8_t bDescriptorType;
 | 
				
			||||||
 | 
						uint8_t bDescriptorSubtype;
 | 
				
			||||||
 | 
						uint16_t bcdCDC;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 16: Union Interface Functional Descriptor */
 | 
				
			||||||
 | 
					struct usb_cdc_union_descriptor {
 | 
				
			||||||
 | 
						uint8_t bFunctionLength;
 | 
				
			||||||
 | 
						uint8_t bDescriptorType;
 | 
				
			||||||
 | 
						uint8_t bDescriptorSubtype;
 | 
				
			||||||
 | 
						uint8_t bControlInterface;
 | 
				
			||||||
 | 
						uint8_t bSubordinateInterface0;
 | 
				
			||||||
 | 
						/* ... */
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Definitions for Abstract Control Model devices from:
 | 
				
			||||||
 | 
					 * "Universal Serial Bus Communications Class Subclass Specification for
 | 
				
			||||||
 | 
					 * PSTN Devices"
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 3: Call Management Functional Descriptor */
 | 
				
			||||||
 | 
					struct usb_cdc_call_management_descriptor {
 | 
				
			||||||
 | 
						uint8_t bFunctionLength;
 | 
				
			||||||
 | 
						uint8_t bDescriptorType;
 | 
				
			||||||
 | 
						uint8_t bDescriptorSubtype;
 | 
				
			||||||
 | 
						uint8_t bmCapabilities;
 | 
				
			||||||
 | 
						uint8_t bDataInterface;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 4: Abstract Control Management Functional Descriptor */
 | 
				
			||||||
 | 
					struct usb_cdc_acm_descriptor {
 | 
				
			||||||
 | 
						uint8_t bFunctionLength;
 | 
				
			||||||
 | 
						uint8_t bDescriptorType;
 | 
				
			||||||
 | 
						uint8_t bDescriptorSubtype;
 | 
				
			||||||
 | 
						uint8_t bmCapabilities;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 13: Class-Specific Request Codes for PSTN subclasses */
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					#define USB_CDC_REQ_SET_LINE_CODING		0x20
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					#define USB_CDC_REQ_SET_CONTROL_LINE_STATE	0x22
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 17: Line Coding Structure */
 | 
				
			||||||
 | 
					struct usb_cdc_line_coding {
 | 
				
			||||||
 | 
						uint32_t dwDTERate;
 | 
				
			||||||
 | 
						uint8_t bCharFormat;
 | 
				
			||||||
 | 
						uint8_t bParityType;
 | 
				
			||||||
 | 
						uint8_t bDataBits;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_cdc_line_coding_bCharFormat {
 | 
				
			||||||
 | 
						USB_CDC_1_STOP_BITS			= 0,
 | 
				
			||||||
 | 
						USB_CDC_1_5_STOP_BITS			= 1,
 | 
				
			||||||
 | 
						USB_CDC_2_STOP_BITS			= 2,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum usb_cdc_line_coding_bParityType {
 | 
				
			||||||
 | 
						USB_CDC_NO_PARITY			= 0,
 | 
				
			||||||
 | 
						USB_CDC_ODD_PARITY			= 1,
 | 
				
			||||||
 | 
						USB_CDC_EVEN_PARITY			= 2,
 | 
				
			||||||
 | 
						USB_CDC_MARK_PARITY			= 3,
 | 
				
			||||||
 | 
						USB_CDC_SPACE_PARITY			= 4,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Table 30: Class-Specific Notification Codes for PSTN subclasses */
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					#define USB_CDC_NOTIFY_SERIAL_STATE		0x20
 | 
				
			||||||
 | 
					/* ... */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Notification Structure */
 | 
				
			||||||
 | 
					struct usb_cdc_notification {
 | 
				
			||||||
 | 
						uint8_t bmRequestType;
 | 
				
			||||||
 | 
						uint8_t bNotification;
 | 
				
			||||||
 | 
						uint16_t wValue;
 | 
				
			||||||
 | 
						uint16_t wIndex;
 | 
				
			||||||
 | 
						uint16_t wLength;
 | 
				
			||||||
 | 
					} __attribute__((packed));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**@}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										101
									
								
								sw/include/usb-desc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								sw/include/usb-desc.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,101 @@
 | 
				
			|||||||
 | 
					/* Teensyduino Core Library
 | 
				
			||||||
 | 
					 * http://www.pjrc.com/teensy/
 | 
				
			||||||
 | 
					 * Copyright (c) 2013 PJRC.COM, LLC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
 | 
					 * a copy of this software and associated documentation files (the
 | 
				
			||||||
 | 
					 * "Software"), to deal in the Software without restriction, including
 | 
				
			||||||
 | 
					 * without limitation the rights to use, copy, modify, merge, publish,
 | 
				
			||||||
 | 
					 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
				
			||||||
 | 
					 * permit persons to whom the Software is furnished to do so, subject to
 | 
				
			||||||
 | 
					 * the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. The above copyright notice and this permission notice shall be 
 | 
				
			||||||
 | 
					 * included in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 2. If the Software is incorporated into a build system that allows 
 | 
				
			||||||
 | 
					 * selection among a list of target devices, then similar target
 | 
				
			||||||
 | 
					 * devices manufactured by PJRC.COM must be included in the list of
 | 
				
			||||||
 | 
					 * target devices and selectable in the same manner.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
				
			||||||
 | 
					 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					 * SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef _usb_desc_h_
 | 
				
			||||||
 | 
					#define _usb_desc_h_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stddef.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_setup_request {
 | 
				
			||||||
 | 
					    union {
 | 
				
			||||||
 | 
					        struct {
 | 
				
			||||||
 | 
					            uint8_t bmRequestType;
 | 
				
			||||||
 | 
					            uint8_t bRequest;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        uint16_t wRequestAndType;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    uint16_t wValue;
 | 
				
			||||||
 | 
					    uint16_t wIndex;
 | 
				
			||||||
 | 
					    uint16_t wLength;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_string_descriptor_struct {
 | 
				
			||||||
 | 
					    uint8_t bLength;
 | 
				
			||||||
 | 
					    uint8_t bDescriptorType;
 | 
				
			||||||
 | 
					    uint16_t wString[];
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NUM_USB_BUFFERS           8
 | 
				
			||||||
 | 
					#define VENDOR_ID                 0x1209    // pid.codes
 | 
				
			||||||
 | 
					#define PRODUCT_ID                0x5bf0    // Assigned to Fomu project
 | 
				
			||||||
 | 
					#define DEVICE_VER                0x0101    // Bootloader version
 | 
				
			||||||
 | 
					#define MANUFACTURER_NAME         u"Foosn"
 | 
				
			||||||
 | 
					#define MANUFACTURER_NAME_LEN     sizeof(MANUFACTURER_NAME)
 | 
				
			||||||
 | 
					#define PRODUCT_NAME              u"Fomu Factory Test " GIT_VERSION
 | 
				
			||||||
 | 
					#define PRODUCT_NAME_LEN          sizeof(PRODUCT_NAME)
 | 
				
			||||||
 | 
					#define EP0_SIZE                  64
 | 
				
			||||||
 | 
					#define NUM_INTERFACE             1
 | 
				
			||||||
 | 
					#define CONFIG_DESC_SIZE          67
 | 
				
			||||||
 | 
					#define USB_DT_INTERFACE_SIZE			9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* USB Descriptor Types - Table 9-5 */
 | 
				
			||||||
 | 
					#define USB_DT_DEVICE				1
 | 
				
			||||||
 | 
					#define USB_DT_CONFIGURATION			2
 | 
				
			||||||
 | 
					#define USB_DT_STRING				3
 | 
				
			||||||
 | 
					#define USB_DT_INTERFACE			4
 | 
				
			||||||
 | 
					#define USB_DT_ENDPOINT				5
 | 
				
			||||||
 | 
					#define USB_DT_DEVICE_QUALIFIER			6
 | 
				
			||||||
 | 
					#define USB_DT_OTHER_SPEED_CONFIGURATION	7
 | 
				
			||||||
 | 
					#define USB_DT_INTERFACE_POWER			8
 | 
				
			||||||
 | 
					/* From ECNs */
 | 
				
			||||||
 | 
					#define USB_DT_OTG				9
 | 
				
			||||||
 | 
					#define USB_DT_DEBUG				10
 | 
				
			||||||
 | 
					#define USB_DT_INTERFACE_ASSOCIATION		11
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_DT_ENDPOINT_SIZE		7
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */
 | 
				
			||||||
 | 
					/* bits 1..0 : transfer type */
 | 
				
			||||||
 | 
					#define USB_ENDPOINT_ATTR_CONTROL		0x00
 | 
				
			||||||
 | 
					#define USB_ENDPOINT_ATTR_ISOCHRONOUS		0x01
 | 
				
			||||||
 | 
					#define USB_ENDPOINT_ATTR_BULK			0x02
 | 
				
			||||||
 | 
					#define USB_ENDPOINT_ATTR_INTERRUPT		0x03
 | 
				
			||||||
 | 
					#define USB_ENDPOINT_ATTR_TYPE		0x03
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    uint16_t  wValue;
 | 
				
			||||||
 | 
					    uint16_t  length;
 | 
				
			||||||
 | 
					    const uint8_t *addr;
 | 
				
			||||||
 | 
					} usb_descriptor_list_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const usb_descriptor_list_t usb_descriptor_list[];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										30
									
								
								sw/include/usb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								sw/include/usb.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					#ifndef __USB_H
 | 
				
			||||||
 | 
					#define __USB_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct usb_setup_request;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_isr(void);
 | 
				
			||||||
 | 
					void usb_init(void);
 | 
				
			||||||
 | 
					void usb_connect(void);
 | 
				
			||||||
 | 
					void usb_idle(void);
 | 
				
			||||||
 | 
					void usb_disconnect(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_irq_happened(void);
 | 
				
			||||||
 | 
					void usb_setup(const struct usb_setup_request *setup);
 | 
				
			||||||
 | 
					void usb_send(const void *data, int total_count);
 | 
				
			||||||
 | 
					void usb_ack_in(void);
 | 
				
			||||||
 | 
					void usb_ack_out(void);
 | 
				
			||||||
 | 
					void usb_err(void);
 | 
				
			||||||
 | 
					int usb_recv(void *buffer, unsigned int buffer_len);
 | 
				
			||||||
 | 
					void usb_poll(void);
 | 
				
			||||||
 | 
					void usb_wait_for_send_done(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
							
								
								
									
										55
									
								
								sw/ld/linker.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								sw/ld/linker.ld
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					INCLUDE output_format.ld
 | 
				
			||||||
 | 
					ENTRY(_start)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__DYNAMIC = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INCLUDE regions.ld
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					SECTIONS
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						.text :
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							_ftext = .;
 | 
				
			||||||
 | 
							*(.text.start)
 | 
				
			||||||
 | 
							*(.text .stub .text.* .gnu.linkonce.t.*)
 | 
				
			||||||
 | 
							_etext = .;
 | 
				
			||||||
 | 
						} > rom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.rodata :
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_frodata = .;
 | 
				
			||||||
 | 
							*(.rodata .rodata.* .gnu.linkonce.r.*)
 | 
				
			||||||
 | 
							*(.rodata1)
 | 
				
			||||||
 | 
							*(.srodata)
 | 
				
			||||||
 | 
							_erodata = .;
 | 
				
			||||||
 | 
						} > rom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.data : AT (ADDR(.rodata) + SIZEOF (.rodata))
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_fdata = .;
 | 
				
			||||||
 | 
							*(.data .data.* .gnu.linkonce.d.*)
 | 
				
			||||||
 | 
							*(.data1)
 | 
				
			||||||
 | 
							_gp = ALIGN(16);
 | 
				
			||||||
 | 
							*(.sdata .sdata.* .gnu.linkonce.s.* .sdata2 .sdata2.*)
 | 
				
			||||||
 | 
							_edata = ALIGN(16); /* Make sure _edata is >= _gp. */
 | 
				
			||||||
 | 
						} > sram
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						.bss :
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_fbss = .;
 | 
				
			||||||
 | 
							*(.dynsbss)
 | 
				
			||||||
 | 
							*(.sbss .sbss.* .gnu.linkonce.sb.*)
 | 
				
			||||||
 | 
							*(.scommon)
 | 
				
			||||||
 | 
							*(.dynbss)
 | 
				
			||||||
 | 
							*(.bss .bss.* .gnu.linkonce.b.*)
 | 
				
			||||||
 | 
							*(COMMON)
 | 
				
			||||||
 | 
							. = ALIGN(4);
 | 
				
			||||||
 | 
							_ebss = .;
 | 
				
			||||||
 | 
							_end = .;
 | 
				
			||||||
 | 
						} > sram
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PROVIDE(_fstack = ORIGIN(sram) + LENGTH(sram) - 4);
 | 
				
			||||||
							
								
								
									
										1
									
								
								sw/ld/output_format.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								sw/ld/output_format.ld
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					OUTPUT_FORMAT("elf32-littleriscv")
 | 
				
			||||||
							
								
								
									
										4
									
								
								sw/ld/regions.ld
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								sw/ld/regions.ld
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					MEMORY {
 | 
				
			||||||
 | 
						sram : ORIGIN = 0x10000000, LENGTH = 4096
 | 
				
			||||||
 | 
						rom : ORIGIN = 0x00000000, LENGTH = 0x00002000
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								sw/src/crt0-vexriscv.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								sw/src/crt0-vexriscv.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					.global main
 | 
				
			||||||
 | 
					.global isr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.section .text.start
 | 
				
			||||||
 | 
					.global _start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					_start:
 | 
				
			||||||
 | 
					  j crt_init
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					  nop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.section .text
 | 
				
			||||||
 | 
					.global  trap_entry
 | 
				
			||||||
 | 
					trap_entry:
 | 
				
			||||||
 | 
					  sw x1,  - 1*4(sp)
 | 
				
			||||||
 | 
					  sw x5,  - 2*4(sp)
 | 
				
			||||||
 | 
					  sw x6,  - 3*4(sp)
 | 
				
			||||||
 | 
					  sw x7,  - 4*4(sp)
 | 
				
			||||||
 | 
					  sw x10, - 5*4(sp)
 | 
				
			||||||
 | 
					  sw x11, - 6*4(sp)
 | 
				
			||||||
 | 
					  sw x12, - 7*4(sp)
 | 
				
			||||||
 | 
					  sw x13, - 8*4(sp)
 | 
				
			||||||
 | 
					  sw x14, - 9*4(sp)
 | 
				
			||||||
 | 
					  sw x15, -10*4(sp)
 | 
				
			||||||
 | 
					  sw x16, -11*4(sp)
 | 
				
			||||||
 | 
					  sw x17, -12*4(sp)
 | 
				
			||||||
 | 
					  sw x28, -13*4(sp)
 | 
				
			||||||
 | 
					  sw x29, -14*4(sp)
 | 
				
			||||||
 | 
					  sw x30, -15*4(sp)
 | 
				
			||||||
 | 
					  sw x31, -16*4(sp)
 | 
				
			||||||
 | 
					  addi sp,sp,-16*4
 | 
				
			||||||
 | 
					  call isr
 | 
				
			||||||
 | 
					  lw x1 , 15*4(sp)
 | 
				
			||||||
 | 
					  lw x5,  14*4(sp)
 | 
				
			||||||
 | 
					  lw x6,  13*4(sp)
 | 
				
			||||||
 | 
					  lw x7,  12*4(sp)
 | 
				
			||||||
 | 
					  lw x10, 11*4(sp)
 | 
				
			||||||
 | 
					  lw x11, 10*4(sp)
 | 
				
			||||||
 | 
					  lw x12,  9*4(sp)
 | 
				
			||||||
 | 
					  lw x13,  8*4(sp)
 | 
				
			||||||
 | 
					  lw x14,  7*4(sp)
 | 
				
			||||||
 | 
					  lw x15,  6*4(sp)
 | 
				
			||||||
 | 
					  lw x16,  5*4(sp)
 | 
				
			||||||
 | 
					  lw x17,  4*4(sp)
 | 
				
			||||||
 | 
					  lw x28,  3*4(sp)
 | 
				
			||||||
 | 
					  lw x29,  2*4(sp)
 | 
				
			||||||
 | 
					  lw x30,  1*4(sp)
 | 
				
			||||||
 | 
					  lw x31,  0*4(sp)
 | 
				
			||||||
 | 
					  addi sp,sp,16*4
 | 
				
			||||||
 | 
					  mret
 | 
				
			||||||
 | 
					  .text
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					crt_init:
 | 
				
			||||||
 | 
					  la sp, _fstack + 4
 | 
				
			||||||
 | 
					  la a0, trap_entry
 | 
				
			||||||
 | 
					  csrw mtvec, a0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bss_init:
 | 
				
			||||||
 | 
					  la a0, _fbss
 | 
				
			||||||
 | 
					  la a1, _ebss
 | 
				
			||||||
 | 
					bss_loop:
 | 
				
			||||||
 | 
					  beq a0,a1,bss_done
 | 
				
			||||||
 | 
					  sw zero,0(a0)
 | 
				
			||||||
 | 
					  add a0,a0,4
 | 
				
			||||||
 | 
					  j bss_loop
 | 
				
			||||||
 | 
					bss_done:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Load DATA */
 | 
				
			||||||
 | 
					  la t0, _erodata
 | 
				
			||||||
 | 
					  la t1, _fdata
 | 
				
			||||||
 | 
					  la t2, _edata
 | 
				
			||||||
 | 
					3:
 | 
				
			||||||
 | 
					  lw t3, 0(t0)
 | 
				
			||||||
 | 
					  sw t3, 0(t1)
 | 
				
			||||||
 | 
					  /* _edata is aligned to 16 bytes. Use word-xfers. */
 | 
				
			||||||
 | 
					  addi t0, t0, 4
 | 
				
			||||||
 | 
					  addi t1, t1, 4
 | 
				
			||||||
 | 
					  bltu t1, t2, 3b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  li a0, 0x880  //880 enable timer + external interrupt sources (until mstatus.MIE is set, they will never trigger an interrupt)
 | 
				
			||||||
 | 
					  csrw mie,a0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  call main
 | 
				
			||||||
 | 
					infinit_loop:
 | 
				
			||||||
 | 
					  j infinit_loop
 | 
				
			||||||
							
								
								
									
										46
									
								
								sw/src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								sw/src/main.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <irq.h>
 | 
				
			||||||
 | 
					#include <usb.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <rgb.h>
 | 
				
			||||||
 | 
					#include <spi.h>
 | 
				
			||||||
 | 
					#include <fomu/csr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ff_spi *spi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void isr(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    unsigned int irqs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    irqs = irq_pending() & irq_getmask();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (irqs & (1 << USB_INTERRUPT))
 | 
				
			||||||
 | 
					        usb_isr();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    rgb_init();
 | 
				
			||||||
 | 
					    spi = spiAlloc();
 | 
				
			||||||
 | 
					    spiInit(spi);
 | 
				
			||||||
 | 
					    irq_setmask(0);
 | 
				
			||||||
 | 
					    irq_setie(1);
 | 
				
			||||||
 | 
					    usb_init();
 | 
				
			||||||
 | 
					    time_init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    (void)argc;
 | 
				
			||||||
 | 
					    (void)argv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    init();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    usb_connect();
 | 
				
			||||||
 | 
					    while (1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        usb_poll();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										89
									
								
								sw/src/rgb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								sw/src/rgb.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,89 @@
 | 
				
			|||||||
 | 
					#include <rgb.h>
 | 
				
			||||||
 | 
					#include <fomu/csr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum led_registers {
 | 
				
			||||||
 | 
					    LEDDCR0 = 8,
 | 
				
			||||||
 | 
					    LEDDBR = 9,
 | 
				
			||||||
 | 
					    LEDDONR = 10,
 | 
				
			||||||
 | 
					    LEDDOFR = 11,
 | 
				
			||||||
 | 
					    LEDDBCRR = 5,
 | 
				
			||||||
 | 
					    LEDDBCFR = 6,
 | 
				
			||||||
 | 
					    LEDDPWRR = 1,
 | 
				
			||||||
 | 
					    LEDDPWRG = 2,
 | 
				
			||||||
 | 
					    LEDDPWRB = 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define BREATHE_ENABLE (1 << 7)
 | 
				
			||||||
 | 
					#define BREATHE_EDGE_ON (0 << 6)
 | 
				
			||||||
 | 
					#define BREATHE_EDGE_BOTH (1 << 6)
 | 
				
			||||||
 | 
					#define BREATHE_MODE_MODULATE (1 << 5)
 | 
				
			||||||
 | 
					#define BREATHE_RATE(x) ((x & 7) << 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define RGB_SWITCH_MODE(x) do { \
 | 
				
			||||||
 | 
					    if (rgb_mode == x) \
 | 
				
			||||||
 | 
					        return; \
 | 
				
			||||||
 | 
					    rgb_mode = x; \
 | 
				
			||||||
 | 
					    /* Toggle LEDD_EXE to force the mode to switch */ \
 | 
				
			||||||
 | 
					    rgb_ctrl_write(           (1 << 1) | (1 << 2)); \
 | 
				
			||||||
 | 
					    rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2)); \
 | 
				
			||||||
 | 
					} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static enum {
 | 
				
			||||||
 | 
					    INVALID = 0,
 | 
				
			||||||
 | 
					    IDLE,
 | 
				
			||||||
 | 
					    WRITING,
 | 
				
			||||||
 | 
					    ERROR,
 | 
				
			||||||
 | 
					    DONE,
 | 
				
			||||||
 | 
					} rgb_mode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rgb_write(uint8_t value, uint8_t addr) {
 | 
				
			||||||
 | 
					    rgb_addr_write(addr);
 | 
				
			||||||
 | 
					    rgb_dat_write(value);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_init(void) {
 | 
				
			||||||
 | 
					    // Turn on the RGB block and current enable, as well as enabling led control
 | 
				
			||||||
 | 
					    rgb_ctrl_write((1 << 0) | (1 << 1) | (1 << 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Enable the LED driver, and set 250 Hz mode.
 | 
				
			||||||
 | 
					    // Also set quick stop, which we'll use to switch patterns quickly.
 | 
				
			||||||
 | 
					    rgb_write((1 << 7) | (1 << 6) | (1 << 3), LEDDCR0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set clock register to 12 MHz / 64 kHz - 1
 | 
				
			||||||
 | 
					    rgb_write((12000000/64000)-1, LEDDBR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rgb_mode_idle();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void rgb_switch_mode(uint8_t mode,
 | 
				
			||||||
 | 
					        uint8_t onr, uint8_t ofr,
 | 
				
			||||||
 | 
					        uint8_t onrate, uint8_t offrate,
 | 
				
			||||||
 | 
					        uint8_t r, uint8_t g, uint8_t b) {
 | 
				
			||||||
 | 
					    RGB_SWITCH_MODE(mode);
 | 
				
			||||||
 | 
					    rgb_write(onr, LEDDONR);
 | 
				
			||||||
 | 
					    rgb_write(ofr, LEDDOFR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rgb_write(BREATHE_ENABLE | BREATHE_EDGE_BOTH
 | 
				
			||||||
 | 
					            | BREATHE_MODE_MODULATE | BREATHE_RATE(onrate), LEDDBCRR);
 | 
				
			||||||
 | 
					    rgb_write(BREATHE_ENABLE | BREATHE_MODE_MODULATE | BREATHE_RATE(offrate), LEDDBCFR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    rgb_write(r, LEDDPWRG); // Red
 | 
				
			||||||
 | 
					    rgb_write(g, LEDDPWRB); // Green
 | 
				
			||||||
 | 
					    rgb_write(b, LEDDPWRR); // Blue
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_mode_idle(void) {
 | 
				
			||||||
 | 
					    rgb_switch_mode(IDLE, 12, 14, 2, 3, 0x00/4, 0x4a/4, 0xe1/4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_mode_writing(void) {
 | 
				
			||||||
 | 
					    rgb_switch_mode(WRITING, 1, 2, 1, 3, 0x00/4, 0x7a/4, 0x51/4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_mode_error(void) {
 | 
				
			||||||
 | 
					    rgb_switch_mode(ERROR, 3, 3, 2, 3, 0xf0/4, 0x0a/4, 0x01/4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void rgb_mode_done(void) {
 | 
				
			||||||
 | 
					    rgb_switch_mode(DONE, 8, 8, 2, 3, 0x14/4, 0xff/4, 0x44/4);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										824
									
								
								sw/src/spi.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										824
									
								
								sw/src/spi.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,824 @@
 | 
				
			|||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					#include <fcntl.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <sys/types.h>
 | 
				
			||||||
 | 
					#include <sys/stat.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					#include <fomu/csr.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "spi.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define fprintf(...) do {} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t do_mirror;
 | 
				
			||||||
 | 
					static uint8_t oe_mirror;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PI_OUTPUT 1
 | 
				
			||||||
 | 
					#define PI_INPUT 0
 | 
				
			||||||
 | 
					#define PI_ALT0 PI_INPUT
 | 
				
			||||||
 | 
					static void gpioSetMode(int pin, int mode) {
 | 
				
			||||||
 | 
					    if (mode)
 | 
				
			||||||
 | 
					        oe_mirror |= 1 << pin;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        oe_mirror &= ~(1 << pin);
 | 
				
			||||||
 | 
					    picorvspi_cfg2_write(oe_mirror);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gpioWrite(int pin, int val) {
 | 
				
			||||||
 | 
					    if (val)
 | 
				
			||||||
 | 
					        do_mirror |= 1 << pin;
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        do_mirror &= ~(1 << pin);
 | 
				
			||||||
 | 
					    picorvspi_cfg1_write(do_mirror);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int gpioRead(int pin) {
 | 
				
			||||||
 | 
					    return !!(picorvspi_stat1_read() & (1 << pin));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void gpioSync(void) {
 | 
				
			||||||
 | 
					    // bbspi_do_write(do_mirror);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SPI_ONLY_SINGLE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum ff_spi_quirks {
 | 
				
			||||||
 | 
						// There is no separate "Write SR 2" command.  Instead,
 | 
				
			||||||
 | 
						// you must write SR2 after writing SR1
 | 
				
			||||||
 | 
						SQ_SR2_FROM_SR1    = (1 << 0),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Don't issue a "Write Enable" command prior to writing
 | 
				
			||||||
 | 
						// a status register
 | 
				
			||||||
 | 
						SQ_SKIP_SR_WEL     = (1 << 1),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Security registers are shifted up by 4 bits
 | 
				
			||||||
 | 
						SQ_SECURITY_NYBBLE_SHIFT = (1 << 2),
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ff_spi {
 | 
				
			||||||
 | 
						enum spi_state state;
 | 
				
			||||||
 | 
						enum spi_type type;
 | 
				
			||||||
 | 
						enum spi_type desired_type;
 | 
				
			||||||
 | 
						struct spi_id id;
 | 
				
			||||||
 | 
						enum ff_spi_quirks quirks;
 | 
				
			||||||
 | 
						int size_override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct {
 | 
				
			||||||
 | 
							int clk;
 | 
				
			||||||
 | 
							int d0;
 | 
				
			||||||
 | 
							int d1;
 | 
				
			||||||
 | 
							int d2;
 | 
				
			||||||
 | 
							int d3;
 | 
				
			||||||
 | 
							int wp;
 | 
				
			||||||
 | 
							int hold;
 | 
				
			||||||
 | 
							int cs;
 | 
				
			||||||
 | 
							int miso;
 | 
				
			||||||
 | 
							int mosi;
 | 
				
			||||||
 | 
						} pins;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_get_id(struct ff_spi *spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_set_state(struct ff_spi *spi, enum spi_state state) {
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
						if (spi->state == state)
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
					#ifndef SPI_ONLY_SINGLE
 | 
				
			||||||
 | 
						switch (state) {
 | 
				
			||||||
 | 
						case SS_SINGLE:
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
					#ifndef SPI_ONLY_SINGLE
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SS_DUAL_RX:
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_INPUT); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SS_DUAL_TX:
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_OUTPUT); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SS_QUAD_RX:
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_INPUT); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_INPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_INPUT);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SS_QUAD_TX:
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_OUTPUT); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case SS_HARDWARE:
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.clk, PI_ALT0); // CLK
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.cs, PI_ALT0); // CE0#
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.mosi, PI_ALT0); // MOSI
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.miso, PI_ALT0); // MISO
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
							gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fprintf(stderr, "Unrecognized spi state\n");
 | 
				
			||||||
 | 
							return;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						spi->state = state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiPause(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						(void)spi;
 | 
				
			||||||
 | 
						gpioSync();
 | 
				
			||||||
 | 
					//	usleep(1);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiBegin(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_SINGLE);
 | 
				
			||||||
 | 
						if ((spi->type == ST_SINGLE) || (spi->type == ST_DUAL)) {
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.wp, 1);
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.hold, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						gpioWrite(spi->pins.cs, 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiEnd(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						(void)spi;
 | 
				
			||||||
 | 
						gpioWrite(spi->pins.cs, 1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t spiXfer(struct ff_spi *spi, uint8_t out) {
 | 
				
			||||||
 | 
						int bit;
 | 
				
			||||||
 | 
						uint8_t in = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (bit = 7; bit >= 0; bit--) {
 | 
				
			||||||
 | 
							if (out & (1 << bit)) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.mosi, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.mosi, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 1);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.miso)) << bit);
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 0);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return in;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spiSingleTx(struct ff_spi *spi, uint8_t out) {
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_SINGLE);
 | 
				
			||||||
 | 
						spiXfer(spi, out);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t spiSingleRx(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_SINGLE);
 | 
				
			||||||
 | 
						return spiXfer(spi, 0xff);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spiDualTx(struct ff_spi *spi, uint8_t out) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int bit;
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_DUAL_TX);
 | 
				
			||||||
 | 
						for (bit = 7; bit >= 0; bit -= 2) {
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 1))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d0, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d0, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 0))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d1, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d1, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 1);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 0);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spiQuadTx(struct ff_spi *spi, uint8_t out) {
 | 
				
			||||||
 | 
						int bit;
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_QUAD_TX);
 | 
				
			||||||
 | 
						for (bit = 7; bit >= 0; bit -= 4) {
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 3))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d0, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d0, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 2))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d1, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d1, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 1))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d2, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d2, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (out & (1 << (bit - 0))) {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d3, 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								gpioWrite(spi->pins.d3, 0);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 1);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 0);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t spiDualRx(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						int bit;
 | 
				
			||||||
 | 
						uint8_t in = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_QUAD_RX);
 | 
				
			||||||
 | 
						for (bit = 7; bit >= 0; bit -= 2) {
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 1);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d0)) << (bit - 1));
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d1)) << (bit - 0));
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 0);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return in;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t spiQuadRx(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						int bit;
 | 
				
			||||||
 | 
						uint8_t in = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_set_state(spi, SS_QUAD_RX);
 | 
				
			||||||
 | 
						for (bit = 7; bit >= 0; bit -= 4) {
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 1);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d0)) << (bit - 3));
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d1)) << (bit - 2));
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d2)) << (bit - 1));
 | 
				
			||||||
 | 
							in |= ((!!gpioRead(spi->pins.d3)) << (bit - 0));
 | 
				
			||||||
 | 
							gpioWrite(spi->pins.clk, 0);
 | 
				
			||||||
 | 
							spiPause(spi);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return in;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiTx(struct ff_spi *spi, uint8_t word) {
 | 
				
			||||||
 | 
						switch (spi->type) {
 | 
				
			||||||
 | 
						case ST_SINGLE:
 | 
				
			||||||
 | 
							spiSingleTx(spi, word);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case ST_DUAL:
 | 
				
			||||||
 | 
							spiDualTx(spi, word);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case ST_QUAD:
 | 
				
			||||||
 | 
						case ST_QPI:
 | 
				
			||||||
 | 
							spiQuadTx(spi, word);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t spiRx(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						switch (spi->type) {
 | 
				
			||||||
 | 
						case ST_SINGLE:
 | 
				
			||||||
 | 
							return spiSingleRx(spi);
 | 
				
			||||||
 | 
						case ST_DUAL:
 | 
				
			||||||
 | 
							return spiDualRx(spi);
 | 
				
			||||||
 | 
						case ST_QUAD:
 | 
				
			||||||
 | 
						case ST_QPI:
 | 
				
			||||||
 | 
							return spiQuadRx(spi);
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return 0xff;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiCommand(struct ff_spi *spi, uint8_t cmd) {
 | 
				
			||||||
 | 
						if (spi->type == ST_QPI)
 | 
				
			||||||
 | 
							spiQuadTx(spi, cmd);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							spiSingleTx(spi, cmd);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t spiCommandRx(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						if (spi->type == ST_QPI)
 | 
				
			||||||
 | 
							return spiQuadRx(spi);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							return spiSingleRx(spi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t spiReadStatus(struct ff_spi *spi, uint8_t sr) {
 | 
				
			||||||
 | 
						uint8_t val = 0xff;
 | 
				
			||||||
 | 
						(void)sr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
						switch (sr) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x05);
 | 
				
			||||||
 | 
							val = spiCommandRx(spi);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case 2:
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x35);
 | 
				
			||||||
 | 
							val = spiCommandRx(spi);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x15);
 | 
				
			||||||
 | 
							val = spiCommandRx(spi);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fprintf(stderr, "unrecognized status register: %d\n", sr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return val;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiWriteSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spi->quirks & SQ_SECURITY_NYBBLE_SHIFT)
 | 
				
			||||||
 | 
							sr <<= 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// erase the register
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x44);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00); // A23-16
 | 
				
			||||||
 | 
						spiCommand(spi, sr);   // A15-8
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00); // A0-7
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_get_id(spi);
 | 
				
			||||||
 | 
						sleep(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// write enable
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x42);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00); // A23-16
 | 
				
			||||||
 | 
						spiCommand(spi, sr);   // A15-8
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00); // A0-7
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < 256; i++)
 | 
				
			||||||
 | 
							spiCommand(spi, security[i]);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_get_id(spi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiReadSecurity(struct ff_spi *spi, uint8_t sr, uint8_t security[256]) {
 | 
				
			||||||
 | 
						if (spi->quirks & SQ_SECURITY_NYBBLE_SHIFT)
 | 
				
			||||||
 | 
							sr <<= 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x48);	// Read security registers
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // A23-16
 | 
				
			||||||
 | 
						spiCommand(spi, sr);    // A15-8
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // A0-7
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
						for (i = 0; i < 256; i++)
 | 
				
			||||||
 | 
							security[i] = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiWriteStatus(struct ff_spi *spi, uint8_t sr, uint8_t val) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch (sr) {
 | 
				
			||||||
 | 
						case 1:
 | 
				
			||||||
 | 
							if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x50);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x01);
 | 
				
			||||||
 | 
							spiCommand(spi, val);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case 2: {
 | 
				
			||||||
 | 
							uint8_t sr1 = 0x00;
 | 
				
			||||||
 | 
							if (spi->quirks & SQ_SR2_FROM_SR1)
 | 
				
			||||||
 | 
								sr1 = spiReadStatus(spi, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x50);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							if (spi->quirks & SQ_SR2_FROM_SR1) {
 | 
				
			||||||
 | 
								spiCommand(spi, 0x01);
 | 
				
			||||||
 | 
								spiCommand(spi, sr1);
 | 
				
			||||||
 | 
								spiCommand(spi, val);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else {
 | 
				
			||||||
 | 
								spiCommand(spi, 0x31);
 | 
				
			||||||
 | 
								spiCommand(spi, val);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case 3:
 | 
				
			||||||
 | 
							if (!(spi->quirks & SQ_SKIP_SR_WEL)) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x50);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x11);
 | 
				
			||||||
 | 
							spiCommand(spi, val);
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fprintf(stderr, "unrecognized status register: %d\n", sr);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					struct spi_id spiId(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						return spi->id;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void spi_decode_id(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spi->id.bytes = -1; // unknown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spi->id.manufacturer_id == 0xef) {
 | 
				
			||||||
 | 
							// spi->id.manufacturer = "Winbond";
 | 
				
			||||||
 | 
							if ((spi->id.memory_type == 0x70)
 | 
				
			||||||
 | 
							 && (spi->id.memory_size == 0x18)) {
 | 
				
			||||||
 | 
								// spi->id.model = "W25Q128JV";
 | 
				
			||||||
 | 
								// spi->id.capacity = "128 Mbit";
 | 
				
			||||||
 | 
								spi->id.bytes = 16 * 1024 * 1024;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spi->id.manufacturer_id == 0x1f) {
 | 
				
			||||||
 | 
							// spi->id.manufacturer = "Adesto";
 | 
				
			||||||
 | 
							 if ((spi->id.memory_type == 0x86)
 | 
				
			||||||
 | 
							  && (spi->id.memory_size == 0x01)) {
 | 
				
			||||||
 | 
								// spi->id.model = "AT25SF161";
 | 
				
			||||||
 | 
								// spi->id.capacity = "16 Mbit";
 | 
				
			||||||
 | 
								spi->id.bytes = 1 * 1024 * 1024;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					static void spi_get_id(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x90);	// Read manufacturer ID
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 1
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 2
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 3
 | 
				
			||||||
 | 
						spi->id.manufacturer_id = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.device_id = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x9f);	// Read device id
 | 
				
			||||||
 | 
						spi->id._manufacturer_id = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.memory_type = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.memory_size = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0xab);	// Read electronic signature
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 1
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 2
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 3
 | 
				
			||||||
 | 
						spi->id.signature = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x4b);	// Read unique ID
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 1
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 2
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 3
 | 
				
			||||||
 | 
						spiCommand(spi, 0x00);  // Dummy byte 4
 | 
				
			||||||
 | 
						spi->id.serial[0] = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.serial[1] = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.serial[2] = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spi->id.serial[3] = spiCommandRx(spi);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_decode_id(spi);
 | 
				
			||||||
 | 
						return;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					void spiOverrideSize(struct ff_spi *spi, uint32_t size) {
 | 
				
			||||||
 | 
						spi->size_override = size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If size is 0, re-read the capacity
 | 
				
			||||||
 | 
						if (!size)
 | 
				
			||||||
 | 
							spi_decode_id(spi);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							spi->id.bytes = size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiSetType(struct ff_spi *spi, enum spi_type type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (spi->type == type)
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef SPI_ONLY_SINGLE
 | 
				
			||||||
 | 
						switch (type) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ST_SINGLE:
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
							if (spi->type == ST_QPI) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0xff);	// Exit QPI Mode
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							spi->type = type;
 | 
				
			||||||
 | 
							spi_set_state(spi, SS_SINGLE);
 | 
				
			||||||
 | 
					#ifndef SPI_ONLY_SINGLE
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ST_DUAL:
 | 
				
			||||||
 | 
							if (spi->type == ST_QPI) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0xff);	// Exit QPI Mode
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							spi->type = type;
 | 
				
			||||||
 | 
							spi_set_state(spi, SS_DUAL_TX);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ST_QUAD:
 | 
				
			||||||
 | 
							if (spi->type == ST_QPI) {
 | 
				
			||||||
 | 
								spiBegin(spi);
 | 
				
			||||||
 | 
								spiCommand(spi, 0xff);	// Exit QPI Mode
 | 
				
			||||||
 | 
								spiEnd(spi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Enable QE bit
 | 
				
			||||||
 | 
							spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spi->type = type;
 | 
				
			||||||
 | 
							spi_set_state(spi, SS_QUAD_TX);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ST_QPI:
 | 
				
			||||||
 | 
							// Enable QE bit
 | 
				
			||||||
 | 
							spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							spiBegin(spi);
 | 
				
			||||||
 | 
							spiCommand(spi, 0x38);		// Enter QPI Mode
 | 
				
			||||||
 | 
							spiEnd(spi);
 | 
				
			||||||
 | 
							spi->type = type;
 | 
				
			||||||
 | 
							spi_set_state(spi, SS_QUAD_TX);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							fprintf(stderr, "Unrecognized SPI type: %d\n", type);
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiIsBusy(struct ff_spi *spi) {
 | 
				
			||||||
 | 
					  	return spiReadStatus(spi, 1) & (1 << 0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiBeginErase32(struct ff_spi *spi, uint32_t erase_addr) {
 | 
				
			||||||
 | 
						// Enable Write-Enable Latch (WEL)
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x52);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 16);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 8);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 0);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiBeginErase64(struct ff_spi *spi, uint32_t erase_addr) {
 | 
				
			||||||
 | 
						// Enable Write-Enable Latch (WEL)
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0xD8);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 16);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 8);
 | 
				
			||||||
 | 
						spiCommand(spi, erase_addr >> 0);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiBeginWrite(struct ff_spi *spi, uint32_t addr, const void *v_data, unsigned int count) {
 | 
				
			||||||
 | 
						const uint8_t write_cmd = 0x02;
 | 
				
			||||||
 | 
						const uint8_t *data = v_data;
 | 
				
			||||||
 | 
						unsigned int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Enable Write-Enable Latch (WEL)
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x06);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// uint8_t sr1 = spiReadStatus(spi, 1);
 | 
				
			||||||
 | 
						// if (!(sr1 & (1 << 1)))
 | 
				
			||||||
 | 
						// 	fprintf(stderr, "error: write-enable latch (WEL) not set, write will probably fail\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, write_cmd);
 | 
				
			||||||
 | 
						spiCommand(spi, addr >> 16);
 | 
				
			||||||
 | 
						spiCommand(spi, addr >> 8);
 | 
				
			||||||
 | 
						spiCommand(spi, addr >> 0);
 | 
				
			||||||
 | 
						for (i = 0; (i < count) && (i < 256); i++)
 | 
				
			||||||
 | 
							spiTx(spi, *data++);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint8_t spiReset(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						// XXX You should check the "Ready" bit before doing this!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Shift to QPI mode, then back to Single mode, to ensure
 | 
				
			||||||
 | 
						// we're actually in Single mode.
 | 
				
			||||||
 | 
						spiSetType(spi, ST_QPI);
 | 
				
			||||||
 | 
						spiSetType(spi, ST_SINGLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x66); // "Enable Reset" command
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0x99); // "Reset Device" command
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// msleep(30);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0xab); // "Resume from Deep Power-Down" command
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int spiInit(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spi->state = SS_UNCONFIGURED;
 | 
				
			||||||
 | 
						spi->type = ST_UNCONFIGURED;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disable memory-mapped mode and enable bit-bang mode
 | 
				
			||||||
 | 
						picorvspi_cfg4_write(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Reset the SPI flash, which will return it to SPI mode even
 | 
				
			||||||
 | 
						// if it's in QPI mode.
 | 
				
			||||||
 | 
						spiReset(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spiSetType(spi, ST_SINGLE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Have the SPI flash pay attention to us
 | 
				
			||||||
 | 
						gpioWrite(spi->pins.hold, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Disable WP
 | 
				
			||||||
 | 
						gpioWrite(spi->pins.wp, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.clk, PI_OUTPUT); // CLK
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.cs, PI_OUTPUT); // CE0#
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.mosi, PI_OUTPUT); // MOSI
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.miso, PI_INPUT); // MISO
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.hold, PI_OUTPUT);
 | 
				
			||||||
 | 
						gpioSetMode(spi->pins.wp, PI_OUTPUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi_get_id(spi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spi->quirks |= SQ_SR2_FROM_SR1;
 | 
				
			||||||
 | 
						if (spi->id.manufacturer_id == 0xef)
 | 
				
			||||||
 | 
							spi->quirks |= SQ_SKIP_SR_WEL | SQ_SECURITY_NYBBLE_SHIFT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiEnableQuad(void) {
 | 
				
			||||||
 | 
						struct ff_spi *spi = spiAlloc();
 | 
				
			||||||
 | 
						spiInit(spi);
 | 
				
			||||||
 | 
						spiWriteStatus(spi, 2, spiReadStatus(spi, 2) | (1 << 1));
 | 
				
			||||||
 | 
						spiFree();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct ff_spi *spiAlloc(void) {
 | 
				
			||||||
 | 
						static struct ff_spi spi;
 | 
				
			||||||
 | 
						return &spi;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiSetPin(struct ff_spi *spi, enum spi_pin pin, int val) {
 | 
				
			||||||
 | 
						switch (pin) {
 | 
				
			||||||
 | 
						case SP_MOSI: spi->pins.mosi = val; break;
 | 
				
			||||||
 | 
						case SP_MISO: spi->pins.miso = val; break;
 | 
				
			||||||
 | 
						case SP_HOLD: spi->pins.hold = val; break;
 | 
				
			||||||
 | 
						case SP_WP: spi->pins.wp = val; break;
 | 
				
			||||||
 | 
						case SP_CS: spi->pins.cs = val; break;
 | 
				
			||||||
 | 
						case SP_CLK: spi->pins.clk = val; break;
 | 
				
			||||||
 | 
						case SP_D0: spi->pins.d0 = val; break;
 | 
				
			||||||
 | 
						case SP_D1: spi->pins.d1 = val; break;
 | 
				
			||||||
 | 
						case SP_D2: spi->pins.d2 = val; break;
 | 
				
			||||||
 | 
						case SP_D3: spi->pins.d3 = val; break;
 | 
				
			||||||
 | 
						default: fprintf(stderr, "unrecognized pin: %d\n", pin); break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiHold(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0xb9);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					void spiUnhold(struct ff_spi *spi) {
 | 
				
			||||||
 | 
						spiBegin(spi);
 | 
				
			||||||
 | 
						spiCommand(spi, 0xab);
 | 
				
			||||||
 | 
						spiEnd(spi);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void spiFree(void) {
 | 
				
			||||||
 | 
						// Re-enable memory-mapped mode
 | 
				
			||||||
 | 
						picorvspi_cfg4_write(0x80);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								sw/src/time.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								sw/src/time.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					#include <fomu/csr.h>
 | 
				
			||||||
 | 
					#include <time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void time_init(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timer0_en_write(0);
 | 
				
			||||||
 | 
						t = 2*SYSTEM_CLOCK_FREQUENCY;
 | 
				
			||||||
 | 
						timer0_reload_write(t);
 | 
				
			||||||
 | 
						timer0_load_write(t);
 | 
				
			||||||
 | 
						timer0_en_write(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int elapsed(int *last_event, int period)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int t, dt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						timer0_update_value_write(1);
 | 
				
			||||||
 | 
						t = timer0_reload_read() - timer0_value_read();
 | 
				
			||||||
 | 
						if(period < 0) {
 | 
				
			||||||
 | 
							*last_event = t;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						dt = t - *last_event;
 | 
				
			||||||
 | 
						if(dt < 0)
 | 
				
			||||||
 | 
							dt += timer0_reload_read();
 | 
				
			||||||
 | 
						if((dt > period) || (dt < 0)) {
 | 
				
			||||||
 | 
							*last_event = t;
 | 
				
			||||||
 | 
							return 1;
 | 
				
			||||||
 | 
						} else
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void msleep(int ms)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					        timer0_en_write(0);
 | 
				
			||||||
 | 
					        timer0_reload_write(0);
 | 
				
			||||||
 | 
					        timer0_load_write(SYSTEM_CLOCK_FREQUENCY/1000*ms);
 | 
				
			||||||
 | 
					        timer0_en_write(1);
 | 
				
			||||||
 | 
					        timer0_update_value_write(1);
 | 
				
			||||||
 | 
					        while(timer0_value_read()) timer0_update_value_write(1);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										220
									
								
								sw/src/usb-desc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								sw/src/usb-desc.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,220 @@
 | 
				
			|||||||
 | 
					/* Teensyduino Core Library
 | 
				
			||||||
 | 
					 * http://www.pjrc.com/teensy/
 | 
				
			||||||
 | 
					 * Copyright (c) 2013 PJRC.COM, LLC.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Permission is hereby granted, free of charge, to any person obtaining
 | 
				
			||||||
 | 
					 * a copy of this software and associated documentation files (the
 | 
				
			||||||
 | 
					 * "Software"), to deal in the Software without restriction, including
 | 
				
			||||||
 | 
					 * without limitation the rights to use, copy, modify, merge, publish,
 | 
				
			||||||
 | 
					 * distribute, sublicense, and/or sell copies of the Software, and to
 | 
				
			||||||
 | 
					 * permit persons to whom the Software is furnished to do so, subject to
 | 
				
			||||||
 | 
					 * the following conditions:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 1. The above copyright notice and this permission notice shall be 
 | 
				
			||||||
 | 
					 * included in all copies or substantial portions of the Software.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 2. If the Software is incorporated into a build system that allows 
 | 
				
			||||||
 | 
					 * selection among a list of target devices, then similar target
 | 
				
			||||||
 | 
					 * devices manufactured by PJRC.COM must be included in the list of
 | 
				
			||||||
 | 
					 * target devices and selectable in the same manner.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 | 
				
			||||||
 | 
					 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 | 
				
			||||||
 | 
					 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 | 
				
			||||||
 | 
					 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 | 
				
			||||||
 | 
					 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 | 
				
			||||||
 | 
					 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | 
				
			||||||
 | 
					 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
				
			||||||
 | 
					 * SOFTWARE.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <usb-desc.h>
 | 
				
			||||||
 | 
					#include <usb-cdc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// USB Descriptors are binary data which the USB host reads to
 | 
				
			||||||
 | 
					// automatically detect a USB device's capabilities.  The format
 | 
				
			||||||
 | 
					// and meaning of every field is documented in numerous USB
 | 
				
			||||||
 | 
					// standards.  When working with USB descriptors, despite the
 | 
				
			||||||
 | 
					// complexity of the standards and poor writing quality in many
 | 
				
			||||||
 | 
					// of those documents, remember descriptors are nothing more
 | 
				
			||||||
 | 
					// than constant binary data that tells the USB host what the
 | 
				
			||||||
 | 
					// device can do.  Computers will load drivers based on this data.
 | 
				
			||||||
 | 
					// Those drivers then communicate on the endpoints specified by
 | 
				
			||||||
 | 
					// the descriptors.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// To configure a new combination of interfaces or make minor
 | 
				
			||||||
 | 
					// changes to existing configuration (eg, change the name or ID
 | 
				
			||||||
 | 
					// numbers), usually you would edit "usb_desc.h".  This file
 | 
				
			||||||
 | 
					// is meant to be configured by the header, so generally it is
 | 
				
			||||||
 | 
					// only edited to add completely new USB interfaces or features.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					//   USB Device
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define LSB(n) ((n) & 255)
 | 
				
			||||||
 | 
					#define MSB(n) (((n) >> 8) & 255)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// USB Device Descriptor.  The USB host reads this first, to learn
 | 
				
			||||||
 | 
					// what type of device is connected.
 | 
				
			||||||
 | 
					static const uint8_t device_descriptor[] = {
 | 
				
			||||||
 | 
					    18,                                     // bLength
 | 
				
			||||||
 | 
					    1,                                      // bDescriptorType
 | 
				
			||||||
 | 
					    0x01, 0x02,                             // bcdUSB
 | 
				
			||||||
 | 
					    USB_CLASS_CDC,                          // bDeviceClass
 | 
				
			||||||
 | 
					    0x00,                                   // bDeviceSubClass
 | 
				
			||||||
 | 
					    0x00,                                   // bDeviceProtocol
 | 
				
			||||||
 | 
					    EP0_SIZE,                               // bMaxPacketSize0
 | 
				
			||||||
 | 
					    LSB(VENDOR_ID), MSB(VENDOR_ID),         // idVendor
 | 
				
			||||||
 | 
					    LSB(PRODUCT_ID), MSB(PRODUCT_ID),       // idProduct
 | 
				
			||||||
 | 
					    LSB(DEVICE_VER), MSB(DEVICE_VER),       // bcdDevice
 | 
				
			||||||
 | 
					    1,                                      // iManufacturer
 | 
				
			||||||
 | 
					    2,                                      // iProduct
 | 
				
			||||||
 | 
					    0,                                      // iSerialNumber
 | 
				
			||||||
 | 
					    1                                       // bNumConfigurations
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// These descriptors must NOT be "const", because the USB DMA
 | 
				
			||||||
 | 
					// has trouble accessing flash memory with enough bandwidth
 | 
				
			||||||
 | 
					// while the processor is executing from flash.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					//   USB Configuration
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// USB Configuration Descriptor.  This huge descriptor tells all
 | 
				
			||||||
 | 
					// of the devices capbilities.
 | 
				
			||||||
 | 
					static const uint8_t config_descriptor[CONFIG_DESC_SIZE] = {
 | 
				
			||||||
 | 
					    // configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
 | 
				
			||||||
 | 
					    9,                                      // bLength;
 | 
				
			||||||
 | 
					    2,                                      // bDescriptorType;
 | 
				
			||||||
 | 
					    LSB(CONFIG_DESC_SIZE),                  // wTotalLength
 | 
				
			||||||
 | 
					    MSB(CONFIG_DESC_SIZE),
 | 
				
			||||||
 | 
					    NUM_INTERFACE,                          // bNumInterfaces
 | 
				
			||||||
 | 
					    1,                                      // bConfigurationValue
 | 
				
			||||||
 | 
					    1,                                      // iConfiguration
 | 
				
			||||||
 | 
					    0x80,                                   // bmAttributes
 | 
				
			||||||
 | 
					    50,                                     // bMaxPower
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // interface descriptor, CDC
 | 
				
			||||||
 | 
					    USB_DT_INTERFACE_SIZE,                  // bLength
 | 
				
			||||||
 | 
					    USB_DT_INTERFACE,                       // bDescriptorType
 | 
				
			||||||
 | 
					    0,                                      // bInterfaceNumber
 | 
				
			||||||
 | 
					    0,                                      // bAlternateSetting
 | 
				
			||||||
 | 
					    1,                                      // bNumEndpoints
 | 
				
			||||||
 | 
					    USB_CLASS_CDC,                          // bInterfaceClass
 | 
				
			||||||
 | 
					    USB_CDC_SUBCLASS_ACM,                   // bInterfaceSubClass
 | 
				
			||||||
 | 
					    USB_CDC_PROTOCOL_AT,                    // bInterfaceProtocol
 | 
				
			||||||
 | 
					    0,                                      // iInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Header Functional Descriptor
 | 
				
			||||||
 | 
					    0x05,                                   // bLength: Endpoint Descriptor size
 | 
				
			||||||
 | 
					    CS_INTERFACE,                           // bDescriptorType: CS_INTERFACE
 | 
				
			||||||
 | 
					    USB_CDC_TYPE_HEADER,                    // bDescriptorSubtype: Header Func Desc
 | 
				
			||||||
 | 
					    0x10,                                   // bcdCDC: spec release number
 | 
				
			||||||
 | 
					    0x01,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Call Managment Functional Descriptor
 | 
				
			||||||
 | 
					    0x05,                                   // bFunctionLength
 | 
				
			||||||
 | 
					    CS_INTERFACE,                           // bDescriptorType: CS_INTERFACE
 | 
				
			||||||
 | 
					    USB_CDC_TYPE_CALL_MANAGEMENT,           // bDescriptorSubtype: Call Management Func Desc
 | 
				
			||||||
 | 
					    0,                                      // bmCapabilities: D0+D1
 | 
				
			||||||
 | 
					    1,                                      // bDataInterface: 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // ACM Functional Descriptor
 | 
				
			||||||
 | 
					    0x04,                                   // bFunctionLength
 | 
				
			||||||
 | 
					    CS_INTERFACE,                           // bDescriptorType: CS_INTERFACE
 | 
				
			||||||
 | 
					    USB_CDC_TYPE_ACM,                       // bDescriptorSubtype: Abstract Control Management desc
 | 
				
			||||||
 | 
					    6,                                      // bmCapabilities
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Union Functional Descriptor
 | 
				
			||||||
 | 
					    0x05,                                   // bFunctionLength
 | 
				
			||||||
 | 
					    CS_INTERFACE,                           // bDescriptorType: CS_INTERFACE
 | 
				
			||||||
 | 
					    USB_CDC_TYPE_UNION,                     // bDescriptorSubtype: Union func desc
 | 
				
			||||||
 | 
					    0,                                      // bMasterInterface: Communication class interface
 | 
				
			||||||
 | 
					    1,                                      // bSlaveInterface0: Data Class Interface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Endpoint descriptor
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT_SIZE,                   // bLength
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT,                        // bDescriptorType
 | 
				
			||||||
 | 
					    0x81,                                   // bEndpointAddress
 | 
				
			||||||
 | 
					    USB_ENDPOINT_ATTR_INTERRUPT,            // bmAttributes
 | 
				
			||||||
 | 
					    LSB(16),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    MSB(16),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    255,                                    // bInterval
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // interface descriptor, CDC
 | 
				
			||||||
 | 
					    USB_DT_INTERFACE_SIZE,                  // bLength
 | 
				
			||||||
 | 
					    USB_DT_INTERFACE,                       // bDescriptorType
 | 
				
			||||||
 | 
					    1,                                      // bInterfaceNumber
 | 
				
			||||||
 | 
					    0,                                      // bAlternateSetting
 | 
				
			||||||
 | 
					    2,                                      // bNumEndpoints
 | 
				
			||||||
 | 
					    USB_CLASS_DATA,                         // bInterfaceClass
 | 
				
			||||||
 | 
					    0,                                      // bInterfaceSubClass
 | 
				
			||||||
 | 
					    0,                                      // bInterfaceProtocol
 | 
				
			||||||
 | 
					    0,                                      // iInterface
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Endpoint descriptor
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT_SIZE,                   // bLength
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT,                        // bDescriptorType
 | 
				
			||||||
 | 
					    0x82,                                   // bEndpointAddress
 | 
				
			||||||
 | 
					    USB_ENDPOINT_ATTR_BULK,                 // bmAttributes
 | 
				
			||||||
 | 
					    LSB(64),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    MSB(64),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    1,                                      // bInterval
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Endpoint descriptor
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT_SIZE,                   // bLength
 | 
				
			||||||
 | 
					    USB_DT_ENDPOINT,                        // bDescriptorType
 | 
				
			||||||
 | 
					    0x02,                                   // bEndpointAddress
 | 
				
			||||||
 | 
					    USB_ENDPOINT_ATTR_BULK,                 // bmAttributes
 | 
				
			||||||
 | 
					    LSB(64),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    MSB(64),                                // wMaxPacketSize
 | 
				
			||||||
 | 
					    1,                                      // bInterval
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					//   String Descriptors
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// The descriptors above can provide human readable strings,
 | 
				
			||||||
 | 
					// referenced by index numbers.  These descriptors are the
 | 
				
			||||||
 | 
					// actual string data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct usb_string_descriptor_struct string0 = {
 | 
				
			||||||
 | 
					    4,
 | 
				
			||||||
 | 
					    3,
 | 
				
			||||||
 | 
					    {0x0409}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((aligned(4)))
 | 
				
			||||||
 | 
					static const struct usb_string_descriptor_struct usb_string_manufacturer_name = {
 | 
				
			||||||
 | 
					    2 + MANUFACTURER_NAME_LEN,
 | 
				
			||||||
 | 
					    3,
 | 
				
			||||||
 | 
					    MANUFACTURER_NAME
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					__attribute__((aligned(4)))
 | 
				
			||||||
 | 
					static const struct usb_string_descriptor_struct usb_string_product_name = {
 | 
				
			||||||
 | 
					    2 + PRODUCT_NAME_LEN,
 | 
				
			||||||
 | 
					    3,
 | 
				
			||||||
 | 
					    PRODUCT_NAME
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					//   Descriptors List
 | 
				
			||||||
 | 
					// **************************************************************
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// This table provides access to all the descriptor data above.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const usb_descriptor_list_t usb_descriptor_list[] = {
 | 
				
			||||||
 | 
					    {0x0100, sizeof(device_descriptor), device_descriptor},
 | 
				
			||||||
 | 
					    {0x0200, sizeof(config_descriptor), config_descriptor},
 | 
				
			||||||
 | 
					    {0x0300, 0, (const uint8_t *)&string0},
 | 
				
			||||||
 | 
					    {0x0301, 0, (const uint8_t *)&usb_string_manufacturer_name},
 | 
				
			||||||
 | 
					    {0x0302, 0, (const uint8_t *)&usb_string_product_name},
 | 
				
			||||||
 | 
					    {0, 0, NULL}
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										254
									
								
								sw/src/usb-epfifo.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										254
									
								
								sw/src/usb-epfifo.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,254 @@
 | 
				
			|||||||
 | 
					#include <irq.h>
 | 
				
			||||||
 | 
					#include <riscv.h>
 | 
				
			||||||
 | 
					#include <string.h>
 | 
				
			||||||
 | 
					#include <usb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CSR_USB_EP_0_OUT_EV_PENDING_ADDR
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define EP0OUT_BUFFERS 4
 | 
				
			||||||
 | 
					__attribute__((aligned(4)))
 | 
				
			||||||
 | 
					static uint8_t volatile usb_ep0out_buffer_len[EP0OUT_BUFFERS];
 | 
				
			||||||
 | 
					static uint8_t volatile usb_ep0out_buffer[EP0OUT_BUFFERS][256];
 | 
				
			||||||
 | 
					static uint8_t volatile usb_ep0out_last_tok[EP0OUT_BUFFERS];
 | 
				
			||||||
 | 
					static volatile uint8_t usb_ep0out_wr_ptr;
 | 
				
			||||||
 | 
					static volatile uint8_t usb_ep0out_rd_ptr;
 | 
				
			||||||
 | 
					static const int max_byte_length = 64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const uint8_t * volatile current_data;
 | 
				
			||||||
 | 
					static volatile int current_length;
 | 
				
			||||||
 | 
					static volatile int data_offset;
 | 
				
			||||||
 | 
					static volatile int data_to_send;
 | 
				
			||||||
 | 
					static int next_packet_is_empty;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Note that our PIDs are only bits 2 and 3 of the token,
 | 
				
			||||||
 | 
					// since all other bits are effectively redundant at this point.
 | 
				
			||||||
 | 
					enum USB_PID {
 | 
				
			||||||
 | 
					    USB_PID_OUT   = 0,
 | 
				
			||||||
 | 
					    USB_PID_SOF   = 1,
 | 
				
			||||||
 | 
					    USB_PID_IN    = 2,
 | 
				
			||||||
 | 
					    USB_PID_SETUP = 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enum epfifo_response {
 | 
				
			||||||
 | 
					    EPF_ACK = 0,
 | 
				
			||||||
 | 
					    EPF_NAK = 1,
 | 
				
			||||||
 | 
					    EPF_NONE = 2,
 | 
				
			||||||
 | 
					    EPF_STALL = 3,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define USB_EV_ERROR 1
 | 
				
			||||||
 | 
					#define USB_EV_PACKET 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_idle(void) {
 | 
				
			||||||
 | 
					    usb_ep_0_out_ev_enable_write(0);
 | 
				
			||||||
 | 
					    usb_ep_0_in_ev_enable_write(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reject all incoming data, since there is no handler anymore
 | 
				
			||||||
 | 
					    usb_ep_0_out_respond_write(EPF_NAK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reject outgoing data, since we don't have any to give.
 | 
				
			||||||
 | 
					    usb_ep_0_in_respond_write(EPF_NAK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_disconnect(void) {
 | 
				
			||||||
 | 
					    usb_ep_0_out_ev_enable_write(0);
 | 
				
			||||||
 | 
					    usb_ep_0_in_ev_enable_write(0);
 | 
				
			||||||
 | 
					    irq_setmask(irq_getmask() & ~(1 << USB_INTERRUPT));
 | 
				
			||||||
 | 
					    usb_pullup_out_write(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_connect(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    usb_ep_0_out_ev_pending_write(usb_ep_0_out_ev_enable_read());
 | 
				
			||||||
 | 
					    usb_ep_0_in_ev_pending_write(usb_ep_0_in_ev_pending_read());
 | 
				
			||||||
 | 
					    usb_ep_0_out_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
 | 
				
			||||||
 | 
					    usb_ep_0_in_ev_enable_write(USB_EV_PACKET | USB_EV_ERROR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Accept incoming data by default.
 | 
				
			||||||
 | 
					    usb_ep_0_out_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Reject outgoing data, since we have none to give yet.
 | 
				
			||||||
 | 
					    usb_ep_0_in_respond_write(EPF_NAK);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    usb_pullup_out_write(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						irq_setmask(irq_getmask() | (1 << USB_INTERRUPT));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_init(void) {
 | 
				
			||||||
 | 
					    usb_ep0out_wr_ptr = 0;
 | 
				
			||||||
 | 
					    usb_ep0out_rd_ptr = 0;
 | 
				
			||||||
 | 
					    usb_pullup_out_write(0);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void process_tx(void) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Don't allow requeueing -- only queue more data if we're
 | 
				
			||||||
 | 
					    // currently set up to respond NAK.
 | 
				
			||||||
 | 
					    if (usb_ep_0_in_respond_read() != EPF_NAK) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Prevent us from double-filling the buffer.
 | 
				
			||||||
 | 
					    if (!usb_ep_0_in_ibuf_empty_read()) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!current_data || !current_length) {
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data_offset += data_to_send;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data_to_send = current_length - data_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Clamp the data to the maximum packet length
 | 
				
			||||||
 | 
					    if (data_to_send > max_byte_length) {
 | 
				
			||||||
 | 
					        data_to_send = max_byte_length;
 | 
				
			||||||
 | 
					        next_packet_is_empty = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (data_to_send == max_byte_length) {
 | 
				
			||||||
 | 
					        next_packet_is_empty = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (next_packet_is_empty) {
 | 
				
			||||||
 | 
					        next_packet_is_empty = 0;
 | 
				
			||||||
 | 
					        data_to_send = 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else if (current_data == NULL || data_to_send <= 0) {
 | 
				
			||||||
 | 
					        next_packet_is_empty = 0;
 | 
				
			||||||
 | 
					        current_data = NULL;
 | 
				
			||||||
 | 
					        current_length = 0;
 | 
				
			||||||
 | 
					        data_offset = 0;
 | 
				
			||||||
 | 
					        data_to_send = 0;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int this_offset;
 | 
				
			||||||
 | 
					    for (this_offset = data_offset; this_offset < (data_offset + data_to_send); this_offset++) {
 | 
				
			||||||
 | 
					        usb_ep_0_in_ibuf_head_write(current_data[this_offset]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    usb_ep_0_in_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_send(const void *data, int total_count) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    while ((current_length || current_data))// && usb_ep_0_in_respond_read() != EPF_NAK)
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    current_data = (uint8_t *)data;
 | 
				
			||||||
 | 
					    current_length = total_count;
 | 
				
			||||||
 | 
					    data_offset = 0;
 | 
				
			||||||
 | 
					    data_to_send = 0;
 | 
				
			||||||
 | 
					    process_tx();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_wait_for_send_done(void) {
 | 
				
			||||||
 | 
					    while (current_data && current_length)
 | 
				
			||||||
 | 
					        usb_poll();
 | 
				
			||||||
 | 
					    while ((usb_ep_0_in_dtb_read() & 1) == 1)
 | 
				
			||||||
 | 
					        usb_poll();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_isr(void) {
 | 
				
			||||||
 | 
					    uint8_t ep0o_pending = usb_ep_0_out_ev_pending_read();
 | 
				
			||||||
 | 
					    uint8_t ep0i_pending = usb_ep_0_in_ev_pending_read();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // We got an OUT or a SETUP packet.  Copy it to usb_ep0out_buffer
 | 
				
			||||||
 | 
					    // and clear the "pending" bit.
 | 
				
			||||||
 | 
					    if (ep0o_pending) {
 | 
				
			||||||
 | 
					        uint8_t last_tok = usb_ep_0_out_last_tok_read();
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        int byte_count = 0;
 | 
				
			||||||
 | 
					        usb_ep0out_last_tok[usb_ep0out_wr_ptr] = last_tok;
 | 
				
			||||||
 | 
					        volatile uint8_t * obuf = usb_ep0out_buffer[usb_ep0out_wr_ptr];
 | 
				
			||||||
 | 
					        if (!usb_ep_0_out_obuf_empty_read()) {
 | 
				
			||||||
 | 
					            while (!usb_ep_0_out_obuf_empty_read()) {
 | 
				
			||||||
 | 
					                obuf[byte_count++] = usb_ep_0_out_obuf_head_read();
 | 
				
			||||||
 | 
					                usb_ep_0_out_obuf_head_write(0);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (byte_count >= 2)
 | 
				
			||||||
 | 
					            usb_ep0out_buffer_len[usb_ep0out_wr_ptr] = byte_count - 2 /* Strip off CRC16 */;
 | 
				
			||||||
 | 
					        usb_ep0out_wr_ptr = (usb_ep0out_wr_ptr + 1) & (EP0OUT_BUFFERS-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (last_tok == USB_PID_SETUP) {
 | 
				
			||||||
 | 
					            usb_ep_0_in_dtb_write(1);
 | 
				
			||||||
 | 
					            data_offset = 0;
 | 
				
			||||||
 | 
					            current_length = 0;
 | 
				
			||||||
 | 
					            current_data = NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        usb_ep_0_out_ev_pending_write(ep0o_pending);
 | 
				
			||||||
 | 
					        usb_ep_0_out_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // We just got an "IN" token.  Send data if we have it.
 | 
				
			||||||
 | 
					    if (ep0i_pending) {
 | 
				
			||||||
 | 
					        usb_ep_0_in_respond_write(EPF_NAK);
 | 
				
			||||||
 | 
					        usb_ep_0_in_ev_pending_write(ep0i_pending);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_ack_in(void) {
 | 
				
			||||||
 | 
					    while (usb_ep_0_in_respond_read() == EPF_ACK)
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    usb_ep_0_in_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_ack_out(void) {
 | 
				
			||||||
 | 
					    while (usb_ep_0_out_respond_read() == EPF_ACK)
 | 
				
			||||||
 | 
					        ;
 | 
				
			||||||
 | 
					    usb_ep_0_out_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_err(void) {
 | 
				
			||||||
 | 
					    usb_ep_0_out_respond_write(EPF_STALL);
 | 
				
			||||||
 | 
					    usb_ep_0_in_respond_write(EPF_STALL);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int usb_recv(void *buffer, unsigned int buffer_len) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Set the OUT response to ACK, since we are in a position to receive data now.
 | 
				
			||||||
 | 
					    usb_ep_0_out_respond_write(EPF_ACK);
 | 
				
			||||||
 | 
					    while (1) {
 | 
				
			||||||
 | 
					        if (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) {
 | 
				
			||||||
 | 
					            if (usb_ep0out_last_tok[usb_ep0out_rd_ptr] == USB_PID_OUT) {
 | 
				
			||||||
 | 
					                unsigned int ep0_buffer_len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr];
 | 
				
			||||||
 | 
					                if (ep0_buffer_len < buffer_len)
 | 
				
			||||||
 | 
					                    buffer_len = ep0_buffer_len;
 | 
				
			||||||
 | 
					                // usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0;
 | 
				
			||||||
 | 
					                memcpy(buffer, (void *)&usb_ep0out_buffer[usb_ep0out_rd_ptr], buffer_len);
 | 
				
			||||||
 | 
					                usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
 | 
				
			||||||
 | 
					                return buffer_len;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_poll(void) {
 | 
				
			||||||
 | 
					    // If some data was received, then process it.
 | 
				
			||||||
 | 
					    while (usb_ep0out_rd_ptr != usb_ep0out_wr_ptr) {
 | 
				
			||||||
 | 
					        const struct usb_setup_request *request = (const struct usb_setup_request *)(usb_ep0out_buffer[usb_ep0out_rd_ptr]);
 | 
				
			||||||
 | 
					        // uint8_t len = usb_ep0out_buffer_len[usb_ep0out_rd_ptr];
 | 
				
			||||||
 | 
					        uint8_t last_tok = usb_ep0out_last_tok[usb_ep0out_rd_ptr];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // usb_ep0out_buffer_len[usb_ep0out_rd_ptr] = 0;
 | 
				
			||||||
 | 
					        usb_ep0out_rd_ptr = (usb_ep0out_rd_ptr + 1) & (EP0OUT_BUFFERS-1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (last_tok == USB_PID_SETUP) {
 | 
				
			||||||
 | 
					            usb_setup(request);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process_tx();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif /* CSR_USB_EP_0_OUT_EV_PENDING_ADDR */
 | 
				
			||||||
							
								
								
									
										114
									
								
								sw/src/usb-setup.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								sw/src/usb-setup.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <unistd.h>
 | 
				
			||||||
 | 
					#include <usb.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <usb-desc.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static uint8_t reply_buffer[8];
 | 
				
			||||||
 | 
					static uint8_t usb_configuration = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void usb_setup(const struct usb_setup_request *setup)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const uint8_t *data = NULL;
 | 
				
			||||||
 | 
					    uint32_t datalen = 0;
 | 
				
			||||||
 | 
					    const usb_descriptor_list_t *list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (setup->wRequestAndType)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					    case 0x0500: // SET_ADDRESS
 | 
				
			||||||
 | 
					    case 0x0b01: // SET_INTERFACE
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0900: // SET_CONFIGURATION
 | 
				
			||||||
 | 
					        usb_configuration = setup->wValue;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0880: // GET_CONFIGURATION
 | 
				
			||||||
 | 
					        reply_buffer[0] = usb_configuration;
 | 
				
			||||||
 | 
					        datalen = 1;
 | 
				
			||||||
 | 
					        data = reply_buffer;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0080: // GET_STATUS (device)
 | 
				
			||||||
 | 
					        reply_buffer[0] = 0;
 | 
				
			||||||
 | 
					        reply_buffer[1] = 0;
 | 
				
			||||||
 | 
					        datalen = 2;
 | 
				
			||||||
 | 
					        data = reply_buffer;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0082: // GET_STATUS (endpoint)
 | 
				
			||||||
 | 
					        if (setup->wIndex > 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            usb_err();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        reply_buffer[0] = 0;
 | 
				
			||||||
 | 
					        reply_buffer[1] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // XXX handle endpoint stall here
 | 
				
			||||||
 | 
					        data = reply_buffer;
 | 
				
			||||||
 | 
					        datalen = 2;
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0102: // CLEAR_FEATURE (endpoint)
 | 
				
			||||||
 | 
					        if (setup->wIndex > 0 || setup->wValue != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO: do we need to handle IN vs OUT here?
 | 
				
			||||||
 | 
					            usb_err();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0302: // SET_FEATURE (endpoint)
 | 
				
			||||||
 | 
					        if (setup->wIndex > 0 || setup->wValue != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            // TODO: do we need to handle IN vs OUT here?
 | 
				
			||||||
 | 
					            usb_err();
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // XXX: Should we set the stall bit?
 | 
				
			||||||
 | 
					        // USB->DIEP0CTL |= USB_DIEP_CTL_STALL;
 | 
				
			||||||
 | 
					        // TODO: do we need to clear the data toggle here?
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case 0x0680: // GET_DESCRIPTOR
 | 
				
			||||||
 | 
					    case 0x0681:
 | 
				
			||||||
 | 
					        for (list = usb_descriptor_list; 1; list++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (list->addr == NULL)
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            if (setup->wValue == list->wValue)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                data = list->addr;
 | 
				
			||||||
 | 
					                if ((setup->wValue >> 8) == 3)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // for string descriptors, use the descriptor's
 | 
				
			||||||
 | 
					                    // length field, allowing runtime configured
 | 
				
			||||||
 | 
					                    // length.
 | 
				
			||||||
 | 
					                    datalen = *(list->addr);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    datalen = list->length;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                goto send;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        usb_err();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        usb_err();
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					send:
 | 
				
			||||||
 | 
					    if (data && datalen) {
 | 
				
			||||||
 | 
					        if (datalen > setup->wLength)
 | 
				
			||||||
 | 
					            datalen = setup->wLength;
 | 
				
			||||||
 | 
					        usb_send(data, datalen);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        usb_ack_in();
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user