Commit b7f3c485 authored by Tomasz Wlostowski's avatar Tomasz Wlostowski

software/tests/gs_logger: crude VME version (needs cleanup & some fixes)

parent eae0d98c
/*
* Public header for the raw I/O interface for PCI or PCI express interfaces
*
* Copyright (C) 2010 CERN (www.cern.ch)
* Author: Alessandro Rubini <rubini@gnudd.com>
*
* Released according to the GNU GPL, version 2 or any later version.
*
* This work is part of the White Rabbit project, a research effort led
* by CERN, the European Institute for Nuclear Research.
*/
#ifndef __RAWRABBIT_H__
#define __RAWRABBIT_H__
#include <linux/types.h>
#include <linux/ioctl.h>
#ifdef __KERNEL__ /* The initial part of the file is driver-internal stuff */
#include <linux/pci.h>
#include <linux/completion.h>
#include <linux/workqueue.h>
#include <linux/firmware.h>
#include <linux/wait.h>
#include <linux/completion.h>
struct rr_devsel;
struct rr_dev {
struct rr_devsel *devsel;
struct pci_driver *pci_driver;
struct pci_device_id *id_table;
struct pci_dev *pdev; /* non-null after pciprobe */
struct mutex mutex;
wait_queue_head_t q;
void *dmabuf;
char *fwname;
struct timespec irqtime;
unsigned long irqcount;
struct completion complete;
struct resource *area[3]; /* bar 0, 2, 4 */
void *remap[3]; /* ioremap of bar 0, 2, 4 */
unsigned long flags;
struct work_struct work;
const struct firmware *fw;
struct completion fw_load;
void (*load_program)(struct rr_dev *); /* lm32 */
int usecount;
#ifdef IS_SPEC_DEMO
struct miscdevice misc;
char miscname[32]; /* "spec-demo-<bus>-<slot> */
struct list_head list;
#endif
};
extern char *rr_fwname; /* module parameter. If "" then defaults apply */
#define RR_FLAG_REGISTERED 0x00000001
#define RR_FLAG_IRQDISABLE 0x00000002
#define RR_FLAG_IRQREQUEST 0x00000002
#define RR_PROBE_TIMEOUT (HZ) /* for pci_register_drv */
/* These two live in ./loader.c */
extern void rr_ask_firmware(struct rr_dev *dev);
extern void rr_load_firmware(struct work_struct *work);
/* And, for the spec only, this is in ./spec-loader.c */
extern void spec_ask_program(struct rr_dev *dev);
#endif /* __KERNEL__ */
/* By default, the driver registers for this vendor/devid */
#define RR_DEFAULT_VENDOR 0x1a39
#define RR_DEFAULT_DEVICE 0x0004
#define RR_DEFAULT_FWNAME "rrabbit-%P-%p@%b"
#define RR_MAX_FWNAME_SIZE 64
#define RR_DEFAULT_BUFSIZE (1<<20) /* 1MB */
#define RR_PLIST_SIZE 4096 /* no PAGE_SIZE in user space */
#define RR_PLIST_LEN (RR_PLIST_SIZE / sizeof(void *))
#define RR_MAX_BUFSIZE (RR_PLIST_SIZE * RR_PLIST_LEN)
/* This structure is used to select the device to be accessed, via ioctl */
struct rr_devsel {
__u16 vendor;
__u16 device;
__u16 subvendor; /* RR_DEVSEL_UNUSED to ignore subvendor/dev */
__u16 subdevice;
__u16 bus; /* RR_DEVSEL_UNUSED to ignore bus and devfn */
__u16 devfn;
};
#define RR_DEVSEL_UNUSED 0xffff
/* Offsets for BAR areas in llseek() and/or ioctl */
#define RR_BAR_0 0x00000000
#define RR_BAR_2 0x20000000
#define RR_BAR_4 0x40000000
#define RR_BAR_BUF 0xc0000000 /* The DMA buffer */
#define RR_IS_DMABUF(addr) ((addr) >= RR_BAR_BUF)
#define __RR_GET_BAR(x) ((x) >> 28)
#define __RR_SET_BAR(x) ((x) << 28)
#define __RR_GET_OFF(x) ((x) & 0x0fffffff)
static inline int rr_is_valid_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0 || bar == 2 || bar == 4 || bar == 0x0c;
}
static inline int rr_is_dmabuf_bar(unsigned long address)
{
int bar = __RR_GET_BAR(address);
return bar == 0x0c;
}
struct rr_iocmd {
__u32 address; /* bar and offset */
__u32 datasize; /* 1 or 2 or 4 or 8 */
union {
__u8 data8;
__u16 data16;
__u32 data32;
__u64 data64;
};
};
/* ioctl commands */
#define __RR_IOC_MAGIC '4' /* random or so */
#define RR_DEVSEL _IOW(__RR_IOC_MAGIC, 0, struct rr_devsel)
#define RR_DEVGET _IOR(__RR_IOC_MAGIC, 1, struct rr_devsel)
#define RR_READ _IOWR(__RR_IOC_MAGIC, 2, struct rr_iocmd)
#define RR_WRITE _IOW(__RR_IOC_MAGIC, 3, struct rr_iocmd)
#define RR_IRQWAIT _IO(__RR_IOC_MAGIC, 4)
#define RR_IRQENA _IO(__RR_IOC_MAGIC, 5)
#define RR_GETDMASIZE _IO(__RR_IOC_MAGIC, 6)
/* #define RR_SETDMASIZE _IO(__RR_IOC_MAGIC, 7, unsigned long) */
#define RR_GETPLIST _IO(__RR_IOC_MAGIC, 8) /* returns a whole page */
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2])
/* Registers from the gennum header files */
enum {
GNGPIO_BASE = 0xA00,
GNGPIO_DIRECTION_MODE = GNGPIO_BASE + 0x4,
GNGPIO_OUTPUT_ENABLE = GNGPIO_BASE + 0x8,
GNGPIO_OUTPUT_VALUE = GNGPIO_BASE + 0xC,
GNGPIO_INPUT_VALUE = GNGPIO_BASE + 0x10,
FCL_BASE = 0xB00,
FCL_CTRL = FCL_BASE,
FCL_STATUS = FCL_BASE + 0x4,
FCL_IODATA_IN = FCL_BASE + 0x8,
FCL_IODATA_OUT = FCL_BASE + 0xC,
FCL_EN = FCL_BASE + 0x10,
FCL_TIMER_0 = FCL_BASE + 0x14,
FCL_TIMER_1 = FCL_BASE + 0x18,
FCL_CLK_DIV = FCL_BASE + 0x1C,
FCL_IRQ = FCL_BASE + 0x20,
FCL_TIMER_CTRL = FCL_BASE + 0x24,
FCL_IM = FCL_BASE + 0x28,
FCL_TIMER2_0 = FCL_BASE + 0x2C,
FCL_TIMER2_1 = FCL_BASE + 0x30,
FCL_DBG_STS = FCL_BASE + 0x34,
FCL_FIFO = 0xE00,
PCI_SYS_CFG_SYSTEM = 0x800
};
#endif /* __RAWRABBIT_H__ */
#ifndef __RR_IO_H
#define __RR_IO_H
#include <stdint.h>
#include <rawrabbit.h>
int rr_bind(int a_fd);
int rr_init(int bus, int devfn);
int rr_writel(uint32_t data, uint32_t addr);
uint32_t rr_readl(uint32_t addr);
int rr_load_bitstream(const void *data, int size8);
int rr_load_bitstream_from_file(const char *file_name);
#endif
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 fdelay_bus.o spec/tools/speclib.o spec/kernel/loader-ll.o fdelay_dmtd_calibration.o simple-eb.o
OBJS = fdelay_lib.o i2c_master.o onewire.o fdelay_vme.o fdelay_dmtd_calibration.o sveclib/sveclib.o sveclib/libvmebus.o
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Ietherbone
CFLAGS = -I../include -g -Imini_bone -Ispec/tools -Isveclib
ifeq ($(SPEC_SW),)
throw_error:
@echo "SPEC software package location environment variable is not set. Can't compile :("
endif
#ifeq ($(SPEC_SW),)
#throw_error:
# @echo "SPEC software package location environment variable is not set. Can't compile :("
#endif
all: spec lib
all: lib
spec:
ln -s $(SPEC_SW) spec
ln -s $(ETHERBONE) etherbone
#spec:
# ln -s $(SPEC_SW) spec
# ln -s $(ETHERBONE) etherbone
lib: $(OBJS)
gcc -shared -o libfinedelay.so $(OBJS) -letherbone
gcc -shared -o libfinedelay.so $(OBJS)
ar rc libfinedelay.a $(OBJS)
clean:
......
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "fdelay_lib.h"
#include "sveclib/sveclib.h"
#include "fdelay_lib.h"
void printk() {};
static void fd_svec_writel(void *priv, uint32_t data, uint32_t addr)
{
svec_writel(priv, data, addr);
}
static uint32_t fd_svec_readl(void *priv, uint32_t addr)
{
return svec_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
#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;
void *card;
if(!strncmp(location, "eb:", 3))
{
snprintf(ip_addr, sizeof(ip_addr), "udp/%s", location+3);
use_eb = 1;
} else if (!strncmp(location, "svec:"), 5) {
sscanf(location+5, "%d,%d", &bus, &dev_fn);
}
card = svec_open(8);
if(!card)
{
fprintf(stderr,"SVEC probe failed.\n");
return -1;
}
dev->priv_io = card;
dev->writel = fd_svec_writel;
dev->readl = fd_svec_readl;
dev->base_addr = 0x10000;
dbg("Found FD core @ 0x%x\n", base_core);
}
fdelay_device_t *fdelay_create()
{
return (fdelay_device_t *) malloc(sizeof(fdelay_device_t));
}
*.o
svec-cl
svec-fwloader
svec-vuart
OBJS=sveclib.o libvmebus.o
CFLAGS=-I. -Wall -DDEBUG -g
CC=gcc
all: cl fwloader vuart svecmem
cl: svec-cl.o $(OBJS)
gcc -o svec-cl $(OBJS) svec-cl.o
fwloader: svec-fwloader.o $(OBJS)
gcc -o svec-fwloader $(OBJS) svec-fwloader.o
vuart: svec-vuart.o $(OBJS)
gcc -o svec-vuart $(OBJS) svec-vuart.o
svecmem: svecmem.o $(OBJS)
gcc -o svecmem $(OBJS) svecmem.o
clean:
rm -f *.o svec-cl svec-test svec-fwloader svec-vuart
\ No newline at end of file
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!! WARNING !!!!!!!!
!!!!!!!! DEVELOPER USE ONLY !!!!!!!!
!!!!!!!! DO NOT DEPLOY IN PRODUCTION ENVIRONMENTS !!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
sveclib - a tiny userspace library (and a set of tools) allowing developers to play with the svec.
The library provides:
- raw I/O to a spec in particular slot (uses geographical addressing). Currently, there's
a fixed A32/D32/SINGLE mapping available and the memory can be accesed by calling
svec_writel()/svec_readl()
- application FPGA firmware loader (svec-fwloader)
- LM32 CPU firmware loader (svec-cl)
- WR Core virtual UART console (svec-vuart)
All these tools require the slot location to be specified with -b command line switch.
Requirements: Requires vmebus driver to be installed (tested on MEN A20).
Compilation: just run make.
\ No newline at end of file
This diff is collapsed.
/**
* \file libvmebus.h
* \brief VME Bus access user library interface
* \author Sbastien Dugu
* \date 04/02/2009
*
* This library gives userspace applications access to the VME bus
*
* Copyright (c) 2009 \em Sbastien \em Dugu
*
* \par License:
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
*/
#ifndef _LIBVMEBUS_H_INCLUDE_
#define _LIBVMEBUS_H_INCLUDE_
#ifdef __cplusplus
extern "C" {
#endif
#include <vmebus.h>
/**
* \brief Swap a 16-bit halfword bytewise
* \param val The 16-bit halfword to swap
*
* \return The swapped value
*
*/
static inline unsigned short swapbe16(unsigned short val)
{
return (((val & 0xff00) >> 8) | ((val & 0xff) << 8));
}
/**
* \brief Swap a 32-bit word bytewise
* \param val The 32-bit word to swap
*
* \return The swapped value
*
*/
static inline unsigned int swapbe32(unsigned int val)
{
return (((val & 0xff000000) >> 24) | ((val & 0xff0000) >> 8) |
((val & 0xff00) << 8) | ((val & 0xff) << 24));
}
extern int vme_bus_error_check(struct vme_mapping *desc);
extern int vme_bus_error_check_clear(struct vme_mapping *desc, __u64 address);
/* VME address space mapping - CES library emulation */
extern unsigned long find_controller(unsigned long vmeaddr, unsigned long len,
unsigned long am, unsigned long offset,
unsigned long size,
struct pdparam_master *param);
extern unsigned long return_controller(struct vme_mapping *desc);
/* VME address space mapping */
extern void *vme_map(struct vme_mapping *, int);
extern int vme_unmap(struct vme_mapping *, int);
/* DMA access */
extern int vme_dma_read(struct vme_dma *);
extern int vme_dma_write(struct vme_dma *);
#ifdef __cplusplus
}
#endif
#endif /* _LIBVMEBUS_H_INCLUDE_ */
/*
* A tool to program our soft-core (LM32) within the SVEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c;
uint32_t lm32_base = 0x00000;
void *card;
while ((c = getopt (argc, argv, "b:c:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'c':
sscanf(optarg, "%i", &lm32_base);
break;
default:
fprintf(stderr,
"Use: \"%s [-b slot] [-c lm32 base address] <lm32_program.bin>\"\n", argv[0]);
fprintf(stderr,
"By default, the first available SVEC is used and the LM32 is assumed at 0x%x.\n", lm32_base);
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected binary name after options.\n");
exit(1);
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
fprintf(stderr,"Loading..\n");
if(svec_load_lm32(card, argv[optind], lm32_base) < 0)
{
fprintf(stderr, "Loader failure.\n");
exit(1);
}
svec_close(card);
exit (0);
}
/*
* A tool to program the FPGA within the SPEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c;
void *card;
while ((c = getopt (argc, argv, "b:")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
default:
fprintf(stderr,
"Use: \"%s -b slot <fpga_bitstream.bin>\"\n", argv[0]);
exit(1);
}
}
if (optind >= argc) {
fprintf(stderr, "Expected binary name after options.\n");
exit(1);
}
if(bus < 0)
{
fprintf(stderr, "You must specify the slot number.\n");
return -1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
if(svec_load_bitstream(card, argv[optind]) < 0)
{
fprintf(stderr, "Loader failure.\n");
exit(1);
}
svec_close(card);
exit (0);
}
#include <stdio.h>
#include "sveclib.h"
int main()
{
void *card =svec_open(8);
svec_writel(card, 0x1deadbee, 0x20400);
printf("readback:%x\n", svec_readl(card, 0x20400));
}
\ No newline at end of file
/* A simple console for accessing the SVEC virtual UART (i.e. for communicating with the WR Core shell
from a Linux terminal. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <errno.h>
#include "sveclib.h"
static void *card;
static int transfer_byte(int from, int is_control) {
char c;
int ret;
do {
ret = read(from, &c, 1);
} while (ret < 0 && errno == EINTR);
if(ret == 1) {
if(is_control) {
if(c == '\x01') { // C-a
return -1;
}
}
svec_vuart_tx(card, &c, 1);
} else {
fprintf(stderr, "\nnothing to read. probably port disconnected.\n");
return -2;
}
return 0;
}
void term_main(int keep_term)
{
struct termios oldkey, newkey; //place tor old and new port settings for keyboard teletype
int need_exit = 0;
fprintf(stderr, "[press C-a to exit]\n");
if(!keep_term) {
tcgetattr(STDIN_FILENO,&oldkey);
newkey.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = 0;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
}
while(!need_exit) {
fd_set fds;
int ret;
char rx;
struct timeval tv = {0, 10000};
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
ret = select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
if(ret == -1) {
perror("select");
} else if (ret > 0) {
if(FD_ISSET(STDIN_FILENO, &fds)) {
need_exit = transfer_byte(STDIN_FILENO, 1);
}
}
while((svec_vuart_rx(card, &rx, 1)) == 1)
fprintf(stderr,"%c", rx);
}
if(!keep_term)
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
int main(int argc, char **argv)
{
int bus = -1, c;
uint32_t vuart_base = 0x20500;
int keep_term = 0;
while ((c = getopt (argc, argv, "b:u:k")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'u':
sscanf(optarg, "%i", &vuart_base);
break;
case 'k':
keep_term = 1;
break;
default:
fprintf(stderr,
"Use: \"%s [-b slot] [-u VUART base] [-k]\"\n", argv[0]);
fprintf(stderr,
"By default, the VUART is assumed at 0x%x.\n \
-k option keeps the terminal config unchanged.\n", vuart_base);
exit(1);
}
}
if(bus < 0)
{
fprintf(stderr, "Missing slot number.\n");
return -1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
return -1;
}
svec_vuart_init(card, vuart_base);
term_main(keep_term);
svec_close(card);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "libvmebus.h"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <errno.h>
#include <sys/signal.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include "sveclib.h"
#include "xloader_regs.h"
#include "wb_uart.h"
#define BASE_LOADER 0x70000
struct svec_private {
int slot;
void *csr_base;
void *bar_base;
struct vme_mapping csr_mapping;
struct vme_mapping bar_mapping;
uint32_t vuart_base;
};
#define MAX_HANDLES 8
static void *active_handles[MAX_HANDLES] = {0,0,0,0,0,0,0,0};
void add_handle(void *handle)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(!active_handles[i])
{
active_handles[i] = handle;
return;
}
}
void remove_handle(void *handle)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(active_handles[i] == handle)
{
active_handles[i] = NULL;
return;
}
}
void cleanup_self(int sig)
{
int i;
for(i=0;i<MAX_HANDLES;i++)
if(active_handles[i])
{
fprintf(stderr,"[caught %d, forced cleanup]\n", sig);
svec_close(active_handles[i]);
}
// atexit(NULL);
if(sig)
exit(0);
}
void atexit_callback()
{
cleanup_self(0);
}
void *svec_open(int slot)
{
struct svec_private *card = malloc(sizeof(struct svec_private));
if(!card)
return NULL;
signal (SIGKILL, cleanup_self);
signal (SIGSEGV, cleanup_self);
signal (SIGTERM, cleanup_self);
atexit(atexit_callback);
struct vme_mapping *mapping = &card->csr_mapping;
memset(mapping, 0, sizeof(struct vme_mapping));
card->slot = slot;
mapping->am = 0x2f;
mapping->data_width = VME_D32;
mapping->vme_addru = 0;
mapping->vme_addrl = slot * 0x80000;
mapping->sizeu = 0;
mapping->sizel = 0x80000;
mapping->read_prefetch_enabled = 0;
mapping->bcast_select = 0;
mapping->window_num = 0;
card->csr_base = vme_map(mapping, 0);
card->bar_base = NULL;
if(!card->csr_base)
{
fprintf(stderr, "Mapping CSR I/O space failed\n");
free(card);
return NULL;
}
add_handle(card);
return card;
}
void map_bar(struct svec_private *card)
{
struct vme_mapping *mapping = &card->bar_mapping;
memset(mapping, 0, sizeof(struct vme_mapping));
mapping->am = 0x9; // A32
mapping->data_width = VME_D32;
mapping->vme_addru = 0;
mapping->vme_addrl = 0x80000000;
mapping->sizeu = 0;
mapping->sizel = 0xff000;
mapping->read_prefetch_enabled = 0;
mapping->bcast_select = 0;
mapping->window_num = 0;
svec_csr_writel(card, 0x80, 0x7ff60);
svec_csr_writel(card, 0, 0x7ff64);
svec_csr_writel(card, 0, 0x7ff68);
svec_csr_writel(card, 0x24, 0x7ff6c);
svec_csr_writel(card, 0x01, 0x7ff30);
svec_csr_writel(card, 0x10, 0x7fff8);
card->bar_base = vme_map(mapping, 0);
}
void svec_close(void *card)
{
struct svec_private *p = (struct svec_private *) card;
if(!card)
return;
vme_unmap(&p->csr_mapping, 0);
if (p->bar_base)
vme_unmap(&p->bar_mapping, 0);
remove_handle(card);
free(card);
}
void svec_writel(void *card, uint32_t data, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
if(!p->bar_base)
map_bar(p);
*(volatile uint32_t *) (p->bar_base + addr) = swapbe32(data);
}
uint32_t svec_readl(void *card, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
if(!p->bar_base)
map_bar(p);
uint32_t rv = swapbe32(*(volatile uint32_t *) (p->bar_base + addr));
return rv;
}
void svec_csr_writel(void *card, uint32_t data, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
*(volatile uint32_t *) (p->csr_base + addr) = swapbe32(data);
}
uint32_t svec_csr_readl(void *card, uint32_t addr)
{
struct svec_private *p = (struct svec_private *) card;
uint32_t rv = swapbe32(*(volatile uint32_t *) (p->csr_base + addr));
return rv;
}
static char *load_binary_file(const char *filename, size_t *size)
{
int i;
struct stat stbuf;
char *buf;
FILE *f;
f = fopen(filename, "r");
if (!f)
return NULL;
if (fstat(fileno(f), &stbuf))
{
fclose(f);
return NULL;
}
if (!S_ISREG(stbuf.st_mode))
{
fclose(f);
return NULL;
}
buf = malloc(stbuf.st_size);
if (!buf)
{
fclose(f);
return NULL;
}
i = fread(buf, 1, stbuf.st_size, f);
if (i < 0) {
fclose(f);
free(buf);
return NULL;
}
if (i != stbuf.st_size) {
fclose(f);
free(buf);
return NULL;
}
fclose(f);
*size = stbuf.st_size;
return buf;
}
int svec_load_lm32(void *card, const char *filename, uint32_t base_addr)
{
char *buf;
uint32_t *ibuf;
size_t size;
int i;
buf = load_binary_file(filename, &size);
if(!buf)
return -1;
/* Phew... we are there, finally */
svec_writel(card, 0x1deadbee, base_addr + 0x20400);
while ( ! (svec_readl(card, base_addr + 0x20400) & (1<<28)) );
ibuf = (uint32_t *) buf;
for (i = 0; i < (size + 3) / 4; i++)
{
// fprintf(stderr, "i %x\n", i);
svec_writel(card, htonl(ibuf[i]), base_addr + i*4);
}
sync();
for (i = 0; i < (size + 3) / 4; i++) {
uint32_t r = svec_readl(card, base_addr + i * 4);
if (r != htonl(ibuf[i]))
{
fprintf(stderr, "programming error at %x "
"(expected %08x, found %08x)\n", i*4,
htonl(ibuf[i]), r);
return -1;
}
}
sync();
svec_writel(card, 0x0deadbee, base_addr + 0x20400);
return 0;
}
int svec_load_bitstream(void *card, const char *filename)
{
struct svec_private *p = (struct svec_private *) card;
int i = 0;
const uint32_t boot_seq[8] = {0xde, 0xad, 0xbe, 0xef, 0xca, 0xfe, 0xba, 0xbe};
const char svec_idr[4] = "SVEC";
char idr[5];
uint32_t *buf;
size_t size;
buf = (uint32_t * )load_binary_file(filename, &size);
if(!buf)
return -1;
/* magic sequence: unlock bootloader mode, disable application FPGA */
for(i=0;i<8;i++)
svec_csr_writel(card, boot_seq[i], BASE_LOADER + XLDR_REG_BTRIGR);
/* check if we are really talking to a SVEC */
uint32_t idc = svec_csr_readl(card, BASE_LOADER + XLDR_REG_IDR);
idr[0] = (idc >> 24) & 0xff;
idr[1] = (idc >> 16) & 0xff;
idr[2] = (idc >> 8) & 0xff;
idr[3] = (idc >> 0) & 0xff;
idr[4] = 0;
printf("IDCode: '%s'\n", idr);
if(strncmp(idr, svec_idr, 4))
{
fprintf(stderr,"Invalid IDCode value. \n");
free(buf);
return -1;
}
svec_csr_writel(card, XLDR_CSR_SWRST, BASE_LOADER + XLDR_REG_CSR);
svec_csr_writel(card, XLDR_CSR_START | XLDR_CSR_MSBF, BASE_LOADER + XLDR_REG_CSR);
while(i < size) {
if(! (svec_csr_readl(card, BASE_LOADER + XLDR_REG_FIFO_CSR) & XLDR_FIFO_CSR_FULL)) {
int n = (size-i>4?4:size-i);
svec_csr_writel(card, (n - 1) | ((n<4) ? XLDR_FIFO_R0_XLAST : 0), BASE_LOADER + XLDR_REG_FIFO_R0);
svec_csr_writel(card, htonl(buf[i>>2]), BASE_LOADER + XLDR_REG_FIFO_R1);
i+=n;
}
}
free(buf);
while(1)
{
uint32_t rval = svec_csr_readl(card, BASE_LOADER + XLDR_REG_CSR);
if(rval & XLDR_CSR_DONE) {
printf("Bitstream loaded, status: %s\n", (rval & XLDR_CSR_ERROR ? "ERROR" : "OK"));
/* give the VME bus control to App FPGA */
svec_csr_writel(card, XLDR_CSR_EXIT, BASE_LOADER + XLDR_REG_CSR);
return rval & XLDR_CSR_ERROR ? -1 : 0;
}
}
return -1;
};
static int vuart_rx(void *card)
{
struct svec_private *p = (struct svec_private *) card;
int rdr = svec_readl(card, p->vuart_base + UART_REG_HOST_RDR);
if(rdr & UART_HOST_RDR_RDY)
return UART_HOST_RDR_DATA_R(rdr);
else
return -1;
}
static void vuart_tx(void *card, int c)
{
struct svec_private *p = (struct svec_private *) card;
while( svec_readl(card, p->vuart_base + UART_REG_SR) & UART_SR_RX_RDY);
svec_writel(card, UART_HOST_TDR_DATA_W(c), p->vuart_base + UART_REG_HOST_TDR);
}
int svec_vuart_init(void *card, uint32_t base_addr)
{
struct svec_private *p = (struct svec_private *) card;
p->vuart_base = base_addr;
return 0;
}
size_t svec_vuart_rx(void *card, char *buffer, size_t size)
{
size_t s = size, n_rx = 0;
while(s--)
{
int c = vuart_rx(card);
if(c < 0)
return n_rx;
*buffer++ = (char) c;
n_rx ++;
}
return n_rx;
}
size_t svec_vuart_tx(void *card, char *buffer, size_t size)
{
size_t s = size;
while(s--)
vuart_tx(card, *buffer++);
return size;
}
#ifndef __SVECLIB_H
#define __SVECLIB_H
#include <stdint.h>
/* 'Opens' the SVEC card at VME slot [slot].
Returns a handle to the card or NULL in case of failure. */
void *svec_open(int slot);
/* Closes the SVEC handle [card] */
void svec_close(void *card);
/* Loads the FPGA bitstream into card [card] from file [filename].
Returns 0 on success. */
int svec_load_bitstream(void *card, const char *filename);
/* Loads the WRC LM32 firmware into card [card] from file [filename]. starting at
address [base_addr]. Returns 0 on success.
WARNING: using improper base address/FPGA firmware will freeze the computer. */
int svec_load_lm32(void *card, const char *filename, uint32_t base_addr);
/* Raw I/O to BAR4 (Wishbone) */
void svec_writel(void *card, uint32_t data, uint32_t addr);
uint32_t svec_readl(void *card, uint32_t addr);
void svec_csr_writel(void *card, uint32_t data, uint32_t addr);
uint32_t svec_csr_readl(void *card, uint32_t addr);
/* Initializes a virtual UART at base address [base_addr]. */
int svec_vuart_init(void *card, uint32_t base_addr);
/* Virtual uart Rx (VUART->Host) and Tx (Host->VUART) functions */
size_t svec_vuart_rx(void *card, char *buffer, size_t size);
size_t svec_vuart_tx(void *card, char *buffer, size_t size);
int svec_flash_read(void *card, int flash_id, uint32_t offset, void *buffer, uint32_t size);
int svec_flash_write(void *card, int flash_id, uint32_t offset, void *buffer, uint32_t size);
int svec_flash_protect(void *card, int flash_id, uint32_t offset, uint32_t size, int on_off);
#endif
/*
* A tool to program the FPGA within the SPEC.
*
* Alessandro Rubini 2012 for CERN, GPLv2 or later.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <getopt.h>
#include "sveclib.h"
int main(int argc, char **argv)
{
int bus = -1, c, do_write = 0;
uint32_t addr, data;
void *card;
int is_csr = 0;
while ((c = getopt (argc, argv, "b:c")) != -1)
{
switch(c)
{
case 'b':
sscanf(optarg, "%i", &bus);
break;
case 'c':
is_csr= 1;
break;
default:
fprintf(stderr,
"Use: \"%s [-c] -b slot addr [data]\"\n", argv[0]);
exit(1);
}
}
if(bus < 0)
{
fprintf(stderr, "You must specify the slot number.\n");
return -1;
}
if(optind >= argc)
{
fprintf(stderr, "Address expected.\n");
return -1;
}
sscanf(argv[optind++], "%i", &addr);
if(optind < argc)
{
sscanf(argv[optind], "%i", &data);
do_write = 1;
}
card = svec_open(bus);
if(!card)
{
fprintf(stderr, "Can't detect a SVEC card under the given adress. Make sure a SVEC card is present in your PC and the driver is loaded.\n");
exit(1);
}
if(do_write)
svec_writel(card, data, addr);
else
printf("%08x\n", svec_readl(card, addr));
svec_close(card);
return 0;
}
This diff is collapsed.
/*
Register definitions for slave core: Simple Wishbone UART
* File : wb_uart.h
* Author : auto-generated by wbgen2 from simple_uart_wb.wb
* Created : Thu May 3 17:36:38 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE simple_uart_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#define __WBGEN2_REGDEFS_SIMPLE_UART_WB_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Status Register */
/* definitions for field: TX busy in reg: Status Register */
#define UART_SR_TX_BUSY WBGEN2_GEN_MASK(0, 1)
/* definitions for field: RX ready in reg: Status Register */
#define UART_SR_RX_RDY WBGEN2_GEN_MASK(1, 1)
/* definitions for register: Baudrate control register */
/* definitions for register: Transmit data regsiter */
/* definitions for field: Transmit data in reg: Transmit data regsiter */
#define UART_TDR_TX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_TDR_TX_DATA_SHIFT 0
#define UART_TDR_TX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_TDR_TX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Receive data regsiter */
/* definitions for field: Received data in reg: Receive data regsiter */
#define UART_RDR_RX_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_RDR_RX_DATA_SHIFT 0
#define UART_RDR_RX_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_RDR_RX_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for register: Host VUART Tx register */
/* definitions for field: TX Data in reg: Host VUART Tx register */
#define UART_HOST_TDR_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_HOST_TDR_DATA_SHIFT 0
#define UART_HOST_TDR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_HOST_TDR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for field: TX Ready in reg: Host VUART Tx register */
#define UART_HOST_TDR_RDY WBGEN2_GEN_MASK(8, 1)
/* definitions for register: Host VUART Rx register */
/* definitions for field: RX Data in reg: Host VUART Rx register */
#define UART_HOST_RDR_DATA_MASK WBGEN2_GEN_MASK(0, 8)
#define UART_HOST_RDR_DATA_SHIFT 0
#define UART_HOST_RDR_DATA_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define UART_HOST_RDR_DATA_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* definitions for field: RX Ready in reg: Host VUART Rx register */
#define UART_HOST_RDR_RDY WBGEN2_GEN_MASK(8, 1)
/* definitions for field: RX FIFO Count in reg: Host VUART Rx register */
#define UART_HOST_RDR_COUNT_MASK WBGEN2_GEN_MASK(9, 16)
#define UART_HOST_RDR_COUNT_SHIFT 9
#define UART_HOST_RDR_COUNT_W(value) WBGEN2_GEN_WRITE(value, 9, 16)
#define UART_HOST_RDR_COUNT_R(reg) WBGEN2_GEN_READ(reg, 9, 16)
#define UART_REG_SR 0x0
#define UART_REG_HOST_TDR 0x10
#define UART_REG_HOST_RDR 0x14
#endif
/*
Register definitions for slave core: Xilinx FPGA loader
* File : xloader_regs.h
* Author : auto-generated by wbgen2 from xloader_wb.wb
* Created : Thu Jun 21 15:17:30 2012
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE xloader_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_XLOADER_WB_WB
#define __WBGEN2_REGDEFS_XLOADER_WB_WB
#include <inttypes.h>
#if defined( __GNUC__)
#define PACKED __attribute__ ((packed))
#else
#error "Unsupported compiler?"
#endif
#ifndef __WBGEN2_MACROS_DEFINED__
#define __WBGEN2_MACROS_DEFINED__
#define WBGEN2_GEN_MASK(offset, size) (((1<<(size))-1) << (offset))
#define WBGEN2_GEN_WRITE(value, offset, size) (((value) & ((1<<(size))-1)) << (offset))
#define WBGEN2_GEN_READ(reg, offset, size) (((reg) >> (offset)) & ((1<<(size))-1))
#define WBGEN2_SIGN_EXTEND(value, bits) (((value) & (1<<bits) ? ~((1<<(bits))-1): 0 ) | (value))
#endif
/* definitions for register: Control/status register */
/* definitions for field: Start configuration in reg: Control/status register */
#define XLDR_CSR_START WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Configuration done in reg: Control/status register */
#define XLDR_CSR_DONE WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Configuration error in reg: Control/status register */
#define XLDR_CSR_ERROR WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Loader busy in reg: Control/status register */
#define XLDR_CSR_BUSY WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Byte order select in reg: Control/status register */
#define XLDR_CSR_MSBF WBGEN2_GEN_MASK(4, 1)
/* definitions for field: Software resest in reg: Control/status register */
#define XLDR_CSR_SWRST WBGEN2_GEN_MASK(5, 1)
/* definitions for field: Exit bootloader mode in reg: Control/status register */
#define XLDR_CSR_EXIT WBGEN2_GEN_MASK(6, 1)
/* definitions for field: Serial clock divider in reg: Control/status register */
#define XLDR_CSR_CLKDIV_MASK WBGEN2_GEN_MASK(8, 6)
#define XLDR_CSR_CLKDIV_SHIFT 8
#define XLDR_CSR_CLKDIV_W(value) WBGEN2_GEN_WRITE(value, 8, 6)
#define XLDR_CSR_CLKDIV_R(reg) WBGEN2_GEN_READ(reg, 8, 6)
/* definitions for register: Bootloader Trigger Register */
/* definitions for register: GPIO Output Register */
/* definitions for register: ID Register */
/* definitions for register: FIFO 'Bitstream FIFO' data input register 0 */
/* definitions for field: Entry size in reg: FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_FIFO_R0_XSIZE_MASK WBGEN2_GEN_MASK(0, 2)
#define XLDR_FIFO_R0_XSIZE_SHIFT 0
#define XLDR_FIFO_R0_XSIZE_W(value) WBGEN2_GEN_WRITE(value, 0, 2)
#define XLDR_FIFO_R0_XSIZE_R(reg) WBGEN2_GEN_READ(reg, 0, 2)
/* definitions for field: Last xfer in reg: FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_FIFO_R0_XLAST WBGEN2_GEN_MASK(2, 1)
/* definitions for register: FIFO 'Bitstream FIFO' data input register 1 */
/* definitions for field: Data in reg: FIFO 'Bitstream FIFO' data input register 1 */
#define XLDR_FIFO_R1_XDATA_MASK WBGEN2_GEN_MASK(0, 32)
#define XLDR_FIFO_R1_XDATA_SHIFT 0
#define XLDR_FIFO_R1_XDATA_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define XLDR_FIFO_R1_XDATA_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Bitstream FIFO' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO clear in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_CLEAR_BUS WBGEN2_GEN_MASK(18, 1)
/* definitions for field: FIFO counter in reg: FIFO 'Bitstream FIFO' control/status register */
#define XLDR_FIFO_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 8)
#define XLDR_FIFO_CSR_USEDW_SHIFT 0
#define XLDR_FIFO_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 8)
#define XLDR_FIFO_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 8)
/* [0x0]: REG Control/status register */
#define XLDR_REG_CSR 0x00000000
/* [0x4]: REG Bootloader Trigger Register */
#define XLDR_REG_BTRIGR 0x00000004
/* [0x8]: REG GPIO Output Register */
#define XLDR_REG_GPIOR 0x00000008
/* [0xc]: REG ID Register */
#define XLDR_REG_IDR 0x0000000c
/* [0x10]: REG FIFO 'Bitstream FIFO' data input register 0 */
#define XLDR_REG_FIFO_R0 0x00000010
/* [0x14]: REG FIFO 'Bitstream FIFO' data input register 1 */
#define XLDR_REG_FIFO_R1 0x00000014
/* [0x18]: REG FIFO 'Bitstream FIFO' control/status register */
#define XLDR_REG_FIFO_CSR 0x00000018
#endif
TESTS = gs_logger # dmtd_calibration gs_logger random_pulse_test sweep_test temperature_calibration
CFLAGS = -I../include
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm -letherbone
LDFLAGS = -L../lib ../lib/libfinedelay.a -lm
CC=gcc
.PHONY: all
......
......@@ -84,13 +84,16 @@ void log_start(char *log_file_name)
if(!log_file)
{
fprintf(stderr, "Can't open the log file: %s\n", log_file_name);
exit(-1);
// exit(-1);
}
bt.card_id = 0;
bt.type = TYPE_START_LOGGING;
if(log_file)
{
fwrite(&bt, sizeof(struct binary_timestamp), 1, log_file);
fflush(log_file);
}
}
void log_stop()
......@@ -267,7 +270,9 @@ void enable_wr(fdelay_device_t *b)
printf("Locking to WR network ...");
fflush(stdout);
fdelay_configure_sync(b, FDELAY_SYNC_WR);
fdelay_configure_sync(b, FDELAY_SYNC_LOCAL);
return;
while(fdelay_check_sync(b) <= 0)
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment