diff --git a/artiq/runtime/Makefile b/artiq/runtime/Makefile index 6c13b631b..46e3aedb9 100644 --- a/artiq/runtime/Makefile +++ b/artiq/runtime/Makefile @@ -7,7 +7,7 @@ OBJECTS := isr.o clock.o rtiocrg.o flash_storage.o mailbox.o \ session.o log.o analyzer.o moninj.o net_server.o bridge_ctl.o \ ksupport_data.o kloader.o test_mode.o main.o OBJECTS_KSUPPORT := ksupport.o artiq_personality.o mailbox.o \ - bridge.o rtio.o ttl.o dds.o + bridge.o rtio.o ttl.o dds.o spi.o CFLAGS += -I$(LIBALLOC_DIRECTORY) \ -I$(MISOC_DIRECTORY)/software/include/dyld \ diff --git a/artiq/runtime/ksupport.c b/artiq/runtime/ksupport.c index d5825f746..bcdd7d028 100644 --- a/artiq/runtime/ksupport.c +++ b/artiq/runtime/ksupport.c @@ -15,6 +15,7 @@ #include "artiq_personality.h" #include "ttl.h" #include "dds.h" +#include "spi.h" #include "rtio.h" double round(double x); @@ -121,6 +122,9 @@ static const struct symbol runtime_exports[] = { {"dds_batch_exit", &dds_batch_exit}, {"dds_set", &dds_set}, + {"spi_write", &spi_write}, + {"spi_read", &spi_read}, + {"cache_get", &cache_get}, {"cache_put", &cache_put}, diff --git a/artiq/runtime/spi.c b/artiq/runtime/spi.c new file mode 100644 index 000000000..a72e3a4f8 --- /dev/null +++ b/artiq/runtime/spi.c @@ -0,0 +1,50 @@ +#include +#include + +#include "artiq_personality.h" +#include "rtio.h" +#include "log.h" +#include "spi.h" + + +#define DURATION_WRITE (1 << CONFIG_RTIO_FINE_TS_WIDTH) + +void spi_write(long long int timestamp, int channel, int addr, + unsigned int data) +{ + rtio_chan_sel_write(CONFIG_RTIO_SPI_CHANNEL + channel); + rtio_o_address_write(addr); + rtio_o_data_write(data); + rtio_o_timestamp_write(timestamp); + rtio_write_and_process_status(timestamp, channel); +} + + +unsigned int spi_read(long long int timestamp, int channel, int addr) +{ + int status; + long long int time_limit = timestamp + DURATION_WRITE; + unsigned int r; + + spi_write(timestamp, channel, addr | SPI_WB_READ, 0); + + while((status = rtio_i_status_read())) { + if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) { + rtio_i_overflow_reset_write(1); + artiq_raise_from_c("RTIOOverflow", + "RTIO overflow at channel {0}", + channel, 0, 0); + } + if(rtio_get_counter() >= time_limit) { + /* check empty flag again to prevent race condition. + * now we are sure that the time limit has been exceeded. + */ + if(rtio_i_status_read() & RTIO_I_STATUS_EMPTY) + return -1; + } + /* input FIFO is empty - keep waiting */ + } + r = rtio_i_data_read(); + rtio_i_re_write(1); + return r; +} diff --git a/artiq/runtime/spi.h b/artiq/runtime/spi.h new file mode 100644 index 000000000..6a5ba08f1 --- /dev/null +++ b/artiq/runtime/spi.h @@ -0,0 +1,20 @@ +#ifndef __SPI_H +#define __SPI_H + +#include +#include +#include + +#define SPI_ADDR_DATA 0 +#define SPI_ADDR_XFER 1 +#define SPI_ADDR_CONFIG 2 +#define SPI_WB_READ (1 << 2) + +#define SPI_XFER_CS(x) (x) +#define SPI_XFER_WRITE_LENGTH(x) ((x) << 16) +#define SPI_XFER_READ_LENGTH(x) ((x) << 24) + +void spi_write(long long int timestamp, int channel, int address, unsigned int data); +unsigned int spi_read(long long int timestamp, int channel, int address); + +#endif /* __SPI_H */