Commit 3467c1fb authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

software: demo program using Etherbone

parent 87a22048
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
all:
make -C lib
make -C tests
make -C lib SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
clean:
make -C lib clean
make -C tests clean
\ No newline at end of file
make -C lib clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
make -C tests clean SPEC_SW=$(SPEC_SW) ETHERBONE=$(ETHERBONE)
\ No newline at end of file
SPEC_SW ?= $(shell readlink -f ~/wr-repos/spec-sw)
ETHERBONE ?= $(shell readlink -f ~/wr-repos/etherbone-core/api)
OBJS = fdelay_lib.o i2c_master.o onewire.o spec_common.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o
OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_bus.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o simple-eb.o
CFLAGS = -I../include -g -Imini_bone -Ispec/tools
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Ietherbone
ifeq ($(SPEC_SW),)
throw_error:
......@@ -12,9 +14,10 @@ all: spec lib
spec:
ln -s $(SPEC_SW) spec
ln -s $(ETHERBONE) etherbone
lib: $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS) -letherbone
ar rc libfinedelay.a $(OBJS)
clean:
......
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "fdelay_lib.h"
#include "simple-eb.h"
#include "spec/tools/speclib.h"
#include "fdelay_lib.h"
void printk() {};
static void fd_spec_writel(void *priv, uint32_t data, uint32_t addr)
{
spec_writel(priv, data, addr);
}
static uint32_t fd_spec_readl(void *priv, uint32_t addr)
{
return spec_readl(priv, addr);
}
#if 0
static int spec_fdelay_create(fdelay_device_t *dev, int bus, int dev_fn)
{
uint32_t base;
dev->priv_io = spec_open(bus, dev_fn);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = base;
//spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */
return 0;
}
#endif
static void fd_eb_writel(void *priv, uint32_t data, uint32_t addr)
{
ebs_write((eb_device_t) priv, addr, data);
}
static uint32_t fd_eb_readl(void *priv, uint32_t addr)
{
return ebs_read((eb_device_t) priv, addr);
}
#define VENDOR_CERN 0xce42
#define DEVICE_FD_CORE 0xf19ede1a
#define DEVICE_VUART 0xe2d13d04
int fdelay_probe(fdelay_device_t *dev, const char *location)
{
int bus = -1, dev_fn = -1;
char ip_addr[128];
int use_eb = 0;
uint32_t base_core;
if(!strncmp(location, "eb:", 3))
{
snprintf(ip_addr, sizeof(ip_addr), "udp/%s", location+3);
use_eb = 1;
} else if (!strncmp(location, "spec:"), 5) {
sscanf(location+5, "%d,%d", &bus, &dev_fn);
}
if(use_eb)
{
dbg("Probing with Etherbone [%s]\n", ip_addr);
if( ebs_init() != EB_OK)
{
fprintf(stderr,"Can't initialize Etherbone library.\n");
return -1;
}
if(ebs_open((eb_device_t*) &dev->priv_io, ip_addr) != EB_OK)
{
fprintf(stderr,"Can't connect to Etherbone device %s.\n", location);
return -1;
}
if(!ebs_sdb_find_device((eb_device_t ) dev->priv_io, VENDOR_CERN, DEVICE_FD_CORE, 0, &base_core))
{
fprintf(stderr,"Can't detect the FD core. Is the bitstream loaded?\n", location);
return -1;
}
dev->writel = fd_eb_writel;
dev->readl = fd_eb_readl;
dev->base_addr = base_core;
dbg("Found FD core @ 0x%x\n", base_core);
} else {
dbg("Sorry, SPEC temporarily unsupported\n.");
return -1;
}
}
fdelay_device_t *fdelay_create()
{
return (fdelay_device_t *) malloc(sizeof(fdelay_device_t));
}
......@@ -919,12 +919,12 @@ int fdelay_init(fdelay_device_t *dev, int init_flags)
hw->calib.zero_offset[i] = 50000;
}
/* Reset the FMC hardware. */
fd_do_reset(dev, FD_RESET_HW);
/* Initialize the clock system - AD9516 PLL */
oc_spi_init(dev);
if(sgpio_init(dev) < 0)
return -1;
......@@ -1445,11 +1445,11 @@ int fdelay_configure_sync(fdelay_device_t *dev, int mode)
if(mode == FDELAY_SYNC_LOCAL)
{
// fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_TCR);
hw->wr_enabled = 0;
} else {
// fd_writel(0, FD_REG_GCR);
fd_writel(0, FD_REG_GCR);
fd_writel(FD_TCR_WR_ENABLE, FD_REG_TCR);
hw->wr_enabled = 1;
}
......@@ -1459,13 +1459,11 @@ int fdelay_check_sync(fdelay_device_t *dev)
{
fd_decl_private(dev)
// fprintf(stderr, "TCR %x\n", fd_readl(FD_REG_TCR) & FD_TCR_WR_LOCKED);
if(hw->wr_enabled && (fd_readl(FD_REG_TCR) & FD_TCR_WR_LOCKED))
{
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_ISR);
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_IER);
return 1;
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_ISR);
fd_writel(FD_EIC_ISR_SYNC_STATUS, FD_REG_EIC_IER);
return 1;
} else if (!hw->wr_enabled)
return 1;
......
/*
* main.c
*
* Created on: Aug 10, 2012
* Author: bbielawski
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/time.h>
#include <unistd.h>
#include "etherbone.h"
static eb_socket_t socket;
static inline void process_result(eb_status_t result)
{
if (result != EB_OK)
{
printf("Error: %s\n", eb_status(result));
// exit(1);
}
return;
}
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address)
{
int write_done = 0;
void wr_callback(eb_user_data_t data, eb_device_t device, eb_operation_t operation, eb_status_t status)
{
write_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, wr_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_write(cycle, address, EB_DATA32 | EB_LITTLE_ENDIAN, data[i]);
if (autoincrement_address)
address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!write_done) eb_socket_run(socket, 10); //wait forever
return status;
}
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address)
{
int read_done = 0;
void rd_callback(eb_user_data_t data, eb_device_t device, eb_operation_t op, eb_status_t status)
{
static int c = 0;
if (status != EB_OK)
{
fprintf(stderr, "read failed: %s\n", eb_status(status));
exit(-1);
}
for(; op != EB_NULL; op = eb_operation_next(op)) {
/* We read low bits first */
*rdata++ = eb_operation_data(op);
}
read_done = 1;
}
eb_cycle_t cycle;
eb_status_t status = eb_cycle_open(device, NULL, rd_callback, &cycle);
if (status != EB_OK)
return status;
int i;
for (i = 0; i < count; i++)
{
eb_cycle_read(cycle, read_address, EB_DATA32 | EB_LITTLE_ENDIAN, NULL);
if(autoincrement_address)
read_address += 4;
}
eb_cycle_close(cycle);
status = eb_device_flush(device);
while (!read_done) eb_socket_run(socket, -1); //wait forever
return status;
}
uint32_t ebs_read(eb_device_t device, eb_address_t addr)
{
eb_data_t rdata;
ebs_block_read(device, addr, &rdata, 1, 0);
return rdata;
}
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data)
{
ebs_block_write(device, addr, &data, 1, 0);
}
eb_status_t ebs_init()
{
eb_status_t status = EB_OK;
status = eb_socket_open(EB_ABI_CODE, 0, EB_DATA32 | EB_ADDR32, &socket);
process_result(status);
}
eb_status_t ebs_shutdown()
{
return eb_socket_close(socket);
}
eb_status_t ebs_open(eb_device_t *dev, const char *network_address)
{
eb_status_t status = EB_OK;
status = eb_device_open(socket, network_address, EB_DATA32 | EB_ADDR32, 5, dev);
process_result(status);
return status;
}
eb_status_t ebs_close(eb_device_t dev)
{
return eb_device_close(dev);
}
struct bus_record {
int i;
int stop;
eb_address_t addr_first, addr_last;
struct bus_record* parent;
};
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr)
{
struct bus_record br;
int done = 0, found = 0, n = 0;
void scan_cb(eb_user_data_t user, eb_device_t dev, sdb_t sdb, eb_status_t status) {
struct bus_record br;
int devices;
br.parent = (struct bus_record*)user;
br.parent->stop = 1;
if (status != EB_OK) {
fprintf(stderr, "failed to retrieve SDB: %s\n", eb_status(status));
exit(1);
}
devices = sdb->interconnect.sdb_records - 1;
for (br.i = 0; br.i < devices; ++br.i) {
sdb_record_t des;
des = &sdb->record[br.i];
if(des->empty.record_type == sdb_device)
{
if(des->device.sdb_component.product.vendor_id == vendor &&
des->device.sdb_component.product.device_id == device)
{
if(n == seq)
{
*base_addr = des->device.sdb_component.addr_first;
found = 1;
return;
}
n ++;
}
}
}
done = 1;
}
br.parent = 0;
br.i = -1;
br.stop = 0;
br.addr_first = 0;
br.addr_last = ~(eb_address_t)0;
br.addr_last >>= (sizeof(eb_address_t) - (eb_device_width(dev) >> 4))*8;
if(eb_sdb_scan_root(dev, &br, &scan_cb) != EB_OK)
return -1;
while(!done && !found) // fixme: crap code
eb_socket_run(eb_device_socket(dev), -1);
return found;
}
#if 0
main()
{
eb_device_t dev;
uint32_t base;
ebs_init();
ebs_open(&dev, "udp/192.168.10.11");
ebs_sdb_find_device(dev, 0xce42, 0xf19ede1a, 0, &base);
printf("base addr: %x\n", base);
}
#endif
#ifndef __SIMPLE_EB_H
#define __SIMPLE_EB_H
#include <stdint.h>
#include "etherbone.h"
eb_status_t ebs_block_write(eb_device_t device, eb_address_t address, eb_data_t* data, int count, int autoincrement_address);
eb_status_t ebs_block_read(eb_device_t device, eb_address_t read_address, eb_data_t *rdata, int count, int autoincrement_address);
uint32_t ebs_read(eb_device_t device, eb_address_t addr);
void ebs_write(eb_device_t device, eb_address_t addr, eb_data_t data);
eb_status_t ebs_init();
eb_status_t ebs_shutdown();
eb_status_t ebs_open(eb_device_t *dev, const char *network_address);
eb_status_t ebs_close(eb_device_t dev);
int ebs_sdb_find_device(eb_device_t dev, uint32_t vendor, uint32_t device, int seq, uint32_t *base_addr);
#endif
#include <stdio.h>
#include <stdint.h>
#include <getopt.h>
#include "spec/tools/speclib.h"
#include "fdelay_lib.h"
static void fd_spec_writel(void *priv, uint32_t data, uint32_t addr)
{
spec_writel(priv, data, addr);
}
static uint32_t fd_spec_readl(void *priv, uint32_t addr)
{
return spec_readl(priv, addr);
}
int spec_fdelay_create_bd(fdelay_device_t *dev, int bus, int dev_fn, uint32_t base)
{
dev->priv_io = spec_open(bus, dev_fn);
if(!dev->priv_io)
{
fprintf(stderr,"Can't map the SPEC @ %x:%x\n", bus, dev_fn);
return -1;
}
dev->writel = fd_spec_writel;
dev->readl = fd_spec_readl;
dev->base_addr = base;
spec_vuart_init(dev->priv_io, 0xe0500); /* for communication with WRCore during DMTD calibration */
return 0;
}
int spec_fdelay_create(fdelay_device_t *dev, int argc, char *argv[])
{
int bus = -1, dev_fn = -1, c;
uint32_t base = 0x80000;
while ((c = getopt (argc, argv, "b:d:f:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'd':
sscanf(optarg, "%i", &dev_fn);
break;
case 'u':
sscanf(optarg, "%i", &base);
break;
default:
fprintf(stderr,
"Use: \"%s [-b bus] [-d devfn] [-u Fine Delay base] [-k]\"\n", argv[0]);
fprintf(stderr,
"By default, the first available SPEC is used and the FD is assumed at 0x%x.\n", base);
return -1;
}
}
return spec_fdelay_create_bd(dev, bus, dev_fn, base);
}
#!/usr/bin/python2
#!/usr/bin/python
import sys
import PyQt4
......@@ -70,11 +70,7 @@ def on_chk_wr():
if __name__ == "__main__":
import os,sys
if(os.getuid() != 0):
print("Sorry, I must be run as root...");
sys.exit(-1)
card = FineDelay()
card = FineDelay(sys.argv[1])
app = QApplication(sys.argv)
......
......@@ -22,35 +22,17 @@ class fd_timestamp(Structure):
return "%d:%d" % (self.utc, self.nsecs())
class FineDelay:
BASE_ADDR = 0x80000
def __init__(self, bus = -1):
self.fdelay = CDLL('../lib/libfinedelay.so')
# load the firmware for the SPEC:
SYNC_LOCAL = 1
SYNC_WR = 2
self.card = self.fdelay.spec_open(c_int(bus), c_int(-1));
if(self.card == 0):
print ("SPEC enumeration failed");
sys.exit(-1)
if ~os.path.isfile("spec_top_fd.bin"):
print ("No firmware file found. Attempting to download one from OHWR")
import urllib
urllib.urlretrieve ("http://www.ohwr.org/attachments/download/1350/spec_top.bin", "spec_top_fd.bin")
cwd = os.getcwd();
if(self.fdelay.spec_load_bitstream(c_voidp(self.card), c_char_p(cwd + "/spec_top_fd.bin")) < 0):
print ("Firmware loader failure");
sys.exit(-1)
self.fdelay.spec_close(c_voidp(self.card))
self.handle = pointer(create_string_buffer('\000' * 16384)) #allocate some memory for the fdelay_device_t
def __init__(self, location="udp/192.168.10.11"):
self.fdelay = CDLL('../lib/libfinedelay.so')
if(self.fdelay.spec_fdelay_create_bd(self.handle, c_int(bus), c_int(-1), c_ulong(self.BASE_ADDR)) < 0):
self.handle = self.fdelay.fdelay_create();
if(self.fdelay.fdelay_probe(self.handle, c_char_p(location)) < 0):
print ("FD enumeration failed")
sys.exit(-1)
......@@ -68,26 +50,30 @@ class FineDelay:
def conf_readout(self, enable):
self.fdelay.fdelay_configure_readout(self.handle, enable)
# def conf_sync(self, mode):
# self.fdelay.fdelay_configure_sync(self.handle, mode)
def conf_sync(self, mode):
self.fdelay.fdelay_configure_sync(self.handle, mode)
def conf_pulsegen(self, channel, enable, t_start_utc, t_start_coarse, width, delta, count):
t = fd_timestamp(utc=c_ulonglong(t_start_utc), coarse=c_ulong(t_start_coarse))
#print "channel:%d enable:%d start_t:%d width:%d delta:%d count:%d"%(channel, enable, t.utc, width, delta, count)
self.fdelay.fdelay_configure_pulse_gen(self.handle, c_int(channel), c_int(enable), t,
c_ulonglong(width), c_ulonglong(delta), c_int(count))
# def conf_pulsegen(self, channel, enable, t_start_utc, t_start_coarse, width, delta, count):
# t = fd_timestamp(utc=c_ulonglong(t_start_utc), coarse=c_ulong(t_start_coarse))
# #print "channel:%d enable:%d start_t:%d width:%d delta:%d count:%d"%(channel, enable, t.utc, width, delta, count)
# self.fdelay.fdelay_configure_pulse_gen(self.handle, c_int(channel), c_int(enable), t,
# c_ulonglong(width), c_ulonglong(delta), c_int(count))
def set_time(self, utc, coarse):
t = fd_timestamp(utc=c_ulonglong(utc), coarse=c_ulong(coarse))
self.fdelay.fdelay_set_time(self.handle, t)
# def set_time(self, utc, coarse):
# t = fd_timestamp(utc=c_ulonglong(utc), coarse=c_ulong(coarse))
# self.fdelay.fdelay_set_time(self.handle, t)
def get_time(self):
t = fd_timestamp()
self.fdelay.fdelay_get_time(self.handle, byref(t))
return t
# def get_time(self):
# t = fd_timestamp()
# self.fdelay.fdelay_get_time(self.handle, byref(t))
# return t
def get_sync_status(self):
return "none"; #fixme: new WR state machine
c = self.fdelay.fdelay_check_sync(self.handle)
if(c):
return "synced"
else:
return "not synced"
def read_ts(self):
buf = (fd_timestamp * 256)();
......
TESTS = dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
TESTS = gs_logger # dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
CFLAGS = -I../include
LDFLAGS = -L../lib -static -lfinedelay -lm
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm -letherbone
CC=gcc
.PHONY: all
......
......@@ -44,7 +44,7 @@ struct board_def {
int term_on;
int64_t input_offset;
int64_t output_offset;
int hw_index;
char *location;
int in_use;
int fd;
int prev_seq;
......@@ -60,7 +60,7 @@ struct board_def boards[MAX_BOARDS];
static FILE *log_file = NULL;
void log_write(fdelay_time_t *t, int card_id)
void log_write(fdelay_time_t *t, const char *location)
{
struct binary_timestamp bt;
if(!log_file)
......@@ -71,7 +71,7 @@ void log_write(fdelay_time_t *t, int card_id)
bt.ts.seq_id = t->seq_id;
bt.ts.channel = 0;
bt.type = TYPE_TIMESTAMP;
bt.card_id = card_id;
bt.card_id = 0; //card_id; // fixme: hash location string?
fwrite(&bt, sizeof(struct binary_timestamp), 1, log_file);
fflush(log_file);
}
......@@ -216,10 +216,10 @@ void load_config(const char *config_file)
if(!strcmp(cmd, "hw_index"))
if(!strcmp(cmd, "location"))
{
CUR.hw_index = parse_num(args[0]);
printf("Adding board %d, hw_index %x\n", current_board, CUR.hw_index);
CUR.location = strdup(args[0]);
printf("Adding board %d, location %s\n", current_board, CUR.location);
}
......@@ -261,13 +261,12 @@ void load_config(const char *config_file)
#undef CUR
void enable_wr(fdelay_device_t *b, int index)
void enable_wr(fdelay_device_t *b)
{
int lock_retries = 50;
printf("Locking to WR network [board=%d]...", index);
printf("Locking to WR network ...");
fflush(stdout);
fdelay_configure_sync(b, FDELAY_SYNC_LOCAL);
/* sleep(2);
fdelay_configure_sync(b, FDELAY_SYNC_WR);
while(fdelay_check_sync(b) <= 0)
......@@ -283,7 +282,7 @@ void enable_wr(fdelay_device_t *b, int index)
}
printf("\n");
fflush(stdout);*/
fflush(stdout);
}
/* Add two timestamps */
......@@ -313,22 +312,22 @@ int configure_board(struct board_def *bdef)
if(spec_fdelay_create_bd(b, bdef->hw_index >>8, bdef->hw_index & 0xff, 0x80000) < 0)
if(fdelay_probe(b, bdef->location) < 0)
{
fprintf(stderr,"Can't open fdelay board @ hw_index %x\n", bdef->hw_index);
fprintf(stderr,"Can't open fdelay board @ %s\n", bdef->location);
exit(-1);
}
if(fdelay_init(b, 0) < 0)
{
fprintf(stderr,"Can't initialize fdelay board @ hw_index %x\n", bdef->hw_index);
fprintf(stderr,"Can't initialize fdelay board @ %s\n", bdef->location);
exit(-1);
}
bdef->b = b;
fdelay_configure_trigger(bdef->b, 0, bdef->term_on);
enable_wr(b, bdef->hw_index);
enable_wr(b);
int val = bdef->input_offset;
// fdelay_sysfs_set((struct __fdelay_board *)b, "fd-input/user-offset", (uint32_t *)&val);
......@@ -431,9 +430,9 @@ void handle_readout(struct board_def *bdef)
{
t_ps = (t.coarse * 8000LL) + ((t.frac * 8000LL) >> 12);
printf("card 0x%04x, seq %5i: time %lli s, %lli.%03lli ns [count %d] ", bdef->hw_index, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, (t.raw.tsbcr >> 10) & 0x3ff);
printf("card %s, seq %5i: time %lli s, %lli.%03lli ns [count %d] ", bdef->location, t.seq_id, t.utc, t_ps / 1000LL, t_ps % 1000LL, (t.raw.tsbcr >> 10) & 0x3ff);
// printf("raw utc=%lld coarse=%d startoffs=%d suboffs=%d frac=%d [%x]\n", t.raw.utc, t.raw.coarse, t.raw.start_offset, t.raw.subcycle_offset, t.raw.frac- 30000, t.raw.frac);