From b7a74307c50bf28cf91be7c618e1b6092dd50878 Mon Sep 17 00:00:00 2001 From: Jacob Pease Date: Tue, 27 Aug 2024 14:19:56 -0500 Subject: [PATCH] Committing the custom test spitest. --- tests/custom/spitest/Makefile | 112 +++++++++++++++++++++++++++++++++ tests/custom/spitest/spi.h | 87 +++++++++++++++++++++++++ tests/custom/spitest/spitest.c | 78 +++++++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 tests/custom/spitest/Makefile create mode 100644 tests/custom/spitest/spi.h create mode 100644 tests/custom/spitest/spitest.c diff --git a/tests/custom/spitest/Makefile b/tests/custom/spitest/Makefile new file mode 100644 index 000000000..34e83a9e4 --- /dev/null +++ b/tests/custom/spitest/Makefile @@ -0,0 +1,112 @@ +CEXT := c +CPPEXT := cpp +AEXT := s +SEXT := S +SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\) +OBJEXT := o +DEPEXT := d +SRCDIR := . +BUILDDIR := OBJ + +SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort) +OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT)) +OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT)) +OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS)) + +TARGETDIR := bin +TARGET := $(TARGETDIR)/spitest.elf +ROOT := .. +LIBRARY_DIRS := +LIBRARY_FILES := + +MARCH :=-march=rv64imfdc +MABI :=-mabi=lp64d +LINK_FLAGS :=$(MARCH) $(MABI) -nostartfiles +LINKER :=$(ROOT)/linker8000-0000.x + + +AFLAGS =$(MARCH) $(MABI) -W +CFLAGS =$(MARCH) $(MABI) -mcmodel=medany -O2 +AS=riscv64-unknown-elf-as +CC=riscv64-unknown-elf-gcc +AR=riscv64-unknown-elf-ar + + +#Default Make +all: directories $(TARGET).memfile + +#Remake +remake: clean all + +#Make the Directories +directories: + @mkdir -p $(TARGETDIR) + @mkdir -p $(BUILDDIR) + +clean: + rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump + + +#Needed for building additional library projects +ifdef LIBRARY_DIRS +LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%} +INC+=${LIBRARY_DIRS:%=-I%} + +${LIBRARY_DIRS}: + make -C $@ -j 1 + +.PHONY: $(LIBRARY_DIRS) $(TARGET) +endif + + +#Pull in dependency info for *existing* .o files +-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) + +#Link +$(TARGET): $(OBJECTS) $(LIBRARY_DIRS) + $(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER} + + +#Compile +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# gcc won't output dependencies for assembly files for some reason +# most asm files don't have dependencies so the echo will work for now. +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT) + +# C++ +$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT) + @mkdir -p $(dir $@) + $(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list + @$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT) + @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp + @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT) + @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT) + @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp + +# convert to hex +$(TARGET).memfile: $(TARGET) + @echo 'Making object dump file.' + @riscv64-unknown-elf-objdump -D $< > $<.objdump + @echo 'Making memory file' + riscv64-unknown-elf-elf2hex --bit-width 64 --input $^ --output $@ + extractFunctionRadix.sh $<.objdump + mkdir -p ../work/ + cp -f $(TARGETDIR)/* ../work/ diff --git a/tests/custom/spitest/spi.h b/tests/custom/spitest/spi.h new file mode 100644 index 000000000..8f6664392 --- /dev/null +++ b/tests/custom/spitest/spi.h @@ -0,0 +1,87 @@ +#pragma once +#ifndef SPI_HEADER +#define SPI_HEADER + +#include + +#define SPI_BASE 0x13000 /* Base address of SPI device used for SDC */ + +/* register offsets */ +#define SPI_SCKDIV SPI_BASE + 0x00 /* Serial clock divisor */ +#define SPI_SCKMODE SPI_BASE + 0x04 /* Serial clock mode */ +#define SPI_CSID SPI_BASE + 0x10 /* Chip select ID */ +#define SPI_CSDEF SPI_BASE + 0x14 /* Chip select default */ +#define SPI_CSMODE SPI_BASE + 0x18 /* Chip select mode */ +#define SPI_DELAY0 SPI_BASE + 0x28 /* Delay control 0 */ +#define SPI_DELAY1 SPI_BASE + 0x2c /* Delay control 1 */ +#define SPI_FMT SPI_BASE + 0x40 /* Frame format */ +#define SPI_TXDATA SPI_BASE + 0x48 /* Tx FIFO data */ +#define SPI_RXDATA SPI_BASE + 0x4c /* Rx FIFO data */ +#define SPI_TXMARK SPI_BASE + 0x50 /* Tx FIFO [<35;39;29Mwatermark */ +#define SPI_RXMARK SPI_BASE + 0x54 /* Rx FIFO watermark */ + +/* Non-implemented +#define SPI_FCTRL SPI_BASE + 0x60 // SPI flash interface control +#define SPI_FFMT SPI_BASE + 0x64 // SPI flash instruction format +*/ +#define SPI_IE SPI_BASE + 0x70 /* Interrupt Enable Register */ +#define SPI_IP SPI_BASE + 0x74 /* Interrupt Pendings Register */ + +/* delay0 bits */ +#define SIFIVE_SPI_DELAY0_CSSCK(x) ((uint32_t)(x)) +#define SIFIVE_SPI_DELAY0_CSSCK_MASK 0xffU +#define SIFIVE_SPI_DELAY0_SCKCS(x) ((uint32_t)(x) << 16) +#define SIFIVE_SPI_DELAY0_SCKCS_MASK (0xffU << 16) + +/* delay1 bits */ +#define SIFIVE_SPI_DELAY1_INTERCS(x) ((uint32_t)(x)) +#define SIFIVE_SPI_DELAY1_INTERCS_MASK 0xffU +#define SIFIVE_SPI_DELAY1_INTERXFR(x) ((uint32_t)(x) << 16) +#define SIFIVE_SPI_DELAY1_INTERXFR_MASK (0xffU << 16) + +/* csmode bits */ +#define SIFIVE_SPI_CSMODE_MODE_AUTO 0U +#define SIFIVE_SPI_CSMODE_MODE_HOLD 2U +#define SIFIVE_SPI_CSMODE_MODE_OFF 3U + +// inline void write_reg(uintptr_t addr, uint32_t value); +//inline uint32_t read_reg(uintptr_t addr); +//inline void spi_sendbyte(uint8_t byte); +//inline void waittx(); +//inline void waitrx(); +uint8_t spi_txrx(uint8_t byte); +uint8_t spi_dummy(); +//inline uint8_t spi_readbyte(); +//uint64_t spi_read64(); +void spi_init(); +void spi_set_clock(uint32_t clkin, uint32_t clkout); + +static inline void write_reg(uintptr_t addr, uint32_t value) { + volatile uint32_t * loc = (volatile uint32_t *) addr; + *loc = value; +} + +// Read a register +static inline uint32_t read_reg(uintptr_t addr) { + return *(volatile uint32_t *) addr; +} + +// Queues a single byte in the transfer fifo +static inline void spi_sendbyte(uint8_t byte) { + // Write byte to transfer fifo + write_reg(SPI_TXDATA, byte); +} + +static inline void waittx() { + while(!(read_reg(SPI_IP) & 1)) {} +} + +static inline void waitrx() { + while(read_reg(SPI_IP) & 2) {} +} + +static inline uint8_t spi_readbyte() { + return read_reg(SPI_RXDATA); +} + +#endif diff --git a/tests/custom/spitest/spitest.c b/tests/custom/spitest/spitest.c new file mode 100644 index 000000000..4e0fcdd66 --- /dev/null +++ b/tests/custom/spitest/spitest.c @@ -0,0 +1,78 @@ +#include "spi.h" + +// Testing SPI peripheral in loopback mode +// TODO: Need to make sure the configuration I'm using uses loopback +// mode. This can be specified in derivlists.txt +// TODO: + +uint8_t spi_txrx(uint8_t byte) { + spi_sendbyte(byte); + waittx(); + return spi_readbyte(); +} + +uint8_t spi_dummy() { + return spi_txrx(0xff); +} + +void spi_set_clock(uint32_t clkin, uint32_t clkout) { + uint32_t div = (clkin/(2*clkout)) - 1; + write_reg(SPI_SCKDIV, div); +} + +// Initialize Sifive FU540 based SPI Controller +void spi_init(uint32_t clkin) { + // Enable interrupts + write_reg(SPI_IE, 0x3); + + // Set TXMARK to 1. If the number of entries is < 1 + // IP's txwm field will go high. + // Set RXMARK to 0. If the number of entries is > 0 + // IP's rwxm field will go high. + write_reg(SPI_TXMARK, 1); + write_reg(SPI_RXMARK, 0); + + // Set Delay 0 to default + write_reg(SPI_DELAY0, + SIFIVE_SPI_DELAY0_CSSCK(1) | + SIFIVE_SPI_DELAY0_SCKCS(1)); + + // Set Delay 1 to default + write_reg(SPI_DELAY1, + SIFIVE_SPI_DELAY1_INTERCS(1) | + SIFIVE_SPI_DELAY1_INTERXFR(0)); + + // Initialize the SPI controller clock to + // div = (20MHz/(2*400kHz)) - 1 = 24 = 0x18 + write_reg(SPI_SCKDIV, 0x18); +} + +void main() { + spi_init(100000000); + + spi_set_clock(100000000,50000000); + + volatile uint8_t *p = (uint8_t *)(0x8F000000); + int j; + uint64_t n = 0; + + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_HOLD); + //n = 512/8; + + n = 4; + do { + // Send 8 dummy bytes (fifo should be empty) + for (j = 0; j < 8; j++) { + spi_sendbyte(0xaa); + } + + // Reset counter. Process bytes AS THEY COME IN. + for (j = 0; j < 8; j++) { + while (!(read_reg(SPI_IP) & 2)) {} + uint8_t x = spi_readbyte(); + *p++ = x; + } + } while(--n > 0); + + write_reg(SPI_CSMODE, SIFIVE_SPI_CSMODE_MODE_AUTO); +}