Commit 8c9107d2 authored by Dinyar Rabady's avatar Dinyar Rabady
Browse files

Merge branch 'ggrosso/hardware-access-layer-main' into main

parents 9ea1e1c2 e76e32f0
# Dummy readme
\ No newline at end of file
# SCOUTING
40MHz scouting CMS
## Control:
- main.py : python interface to get/set (r/rw) properties
Arguments:
-- board (-b): required; choose ["board0", "board1", ...]
-- register (-r): required; choose ["register0", "register1", ...]
-- action (-a): required; choose ["set", "get"]
-- value (-v): optional; new state for property when action == "set"
-- filelog (-f): optional; path to a .txt file; if not given no logfile is created
-- dump (-d): optional; choose 1 to print out messages on the terminal, 0 otherwise (default = 0)
- functions.c : C functions to read/write in the board using AXI-lite from Xilinx (https://github.com/Xilinx/dma_ip_drivers/tree/master/XDMA/linux-kernel)
### set up:
#### if you don't have a driver already:
- download the Xlinx driver from https://github.com/Xilinx/dma_ip_drivers/
- and follow the instructions to install the Xlinx driver
#### once the driver is mounted proceed as follows:
- create a working directory and download the package:
mkdir $HOME/WORKDIR
git clone https://gitlab.cern.ch/scouting-demonstrator/hardware-access-layer
- build the shared library:
cd $HOME/WORKDIR/SCOUTING
cc -fPIC -shared -o functions.so functions.c
- run main.py
python main.py -b [board_name] -a [set/get] -r [register_name] (-v [new_value] -f [path_to_your_logfile/logfile_name.txt] -d [0/1])
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <byteswap.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/mman.h>
/* ltoh: little to host */
/* htol: little to host */
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ltohl(x) (x)
#define ltohs(x) (x)
#define htoll(x) (x)
#define htols(x) (x)
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ltohl(x) __bswap_32(x)
#define ltohs(x) __bswap_16(x)
#define htoll(x) __bswap_32(x)
#define htols(x) __bswap_16(x)
#endif
#define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]\n", __LINE__, __FILE__, errno, strerror(errno)); } while(0)
#define MAP_SIZE (32*1024UL)
#define MAP_MASK (MAP_SIZE - 1)
int write_bits(char *device_loc, char *address, unsigned int writeval, int verbose)
{
char *device = strdup(device_loc);
off_t target = strtoul(address, 0, 0);
if(verbose>0){
printf("device: %s\n", device);
printf("address: 0x%08x\n", (unsigned int)target);
fflush(stdout);
}
/* open device */
int fd = open(device_loc, O_RDWR | O_SYNC);
if (fd == -1) {
FATAL;
return -1;
}
if(verbose>0){
printf("character device %s opened.\n", device_loc);
fflush(stdout);
}
/* map one page */
void *map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map_base == (void *)-1) {
FATAL;
close(fd);
return -1;
}
if(verbose>0){
printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
}
/* calculate the virtual address to be accessed */
void *virt_addr = map_base + target;
/* Write */
if(verbose>0){
printf("Write 32-bits value 0x%08x to 0x%08x (0x%p)\n",
(unsigned int)writeval, (unsigned int)target,
virt_addr);
fflush(stdout);
}
/* swap 32-bit endianess if host is not little-endian */
writeval = htoll(writeval);
*((uint32_t *) virt_addr) = writeval;
close(fd);
return 0;
};
int read_bits(char *device_loc, char *address, uint32_t *read_result, int verbose)
{
char *device = strdup(device_loc);
off_t target = strtoul(address, 0, 0);
if(verbose>0){
printf("device: %s\n", device);
printf("address: 0x%08x\n", (unsigned int)target);
fflush(stdout);
}
/* open device */
int fd = open(device_loc, O_RDWR | O_SYNC);
if ( fd == -1){
FATAL;
return -1;
}
if(verbose>0){
printf("character device %s opened.\n", device_loc);
fflush(stdout);
}
/* map one page */
void *map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (map_base == (void *)-1){
FATAL;
close(fd);
return -1;
}
if(verbose>0){
printf("Memory mapped at address %p.\n", map_base);
fflush(stdout);
}
/* calculate the virtual address to be accessed */
void *virt_addr = map_base + target;
/* Read */
uint32_t read_result_tmp = *((uint32_t *) virt_addr);
/* swap 32-bit endianess if host is not little-endian */
read_result_tmp = ltohl(read_result_tmp);
if(verbose>0){
printf
("Read 32-bit value at address 0x%08x (%p): 0x%08x\n",
(unsigned int)target, virt_addr,
(unsigned int)read_result_tmp);
fflush(stdout);
}
*read_result = read_result_tmp;
close(fd);
return 0;
};
void printBits(unsigned int num){
unsigned int size = sizeof(unsigned int);
unsigned int maxPow = 1<<(size*8-1);
int i=0;
for(; i<size*8; ++i){
// print last bit and shift left.
printf("%u ",num&maxPow ? 1 : 0);
num = num<<1;
}
fflush(stdout);
};
import sys
import argparse
import math
import ctypes
so_file = "./functions.so"
cfunc = ctypes.CDLL(so_file)
# example of input format --> to be discussed and moved to json file
config_dict = {
"board0" : {
"driver" : "/dev/wz-xdma0_user",
"register" : {
"register0" : {
"location": "0x00000000",
"offset" : 0,
"width" : 10,
},
"register1" : {
"location": "0x00000000",
"offset" : 10,
"width" : 20
}
}
},
"board1" : {
"driver" : "/dev/wz-xdma1_user",
"register" : {
"register0" : {
"location": "0x00000000",
"offset" : 0,
"width" : 32
},
"register1" : {
"location": "0x00000004",
"offset" : 30,
"width" : 2
}
}
}
#"board2" : "/dev/wz-xdma2_user",
#...
}
actions = ["get", "set"]
def ReadProperty(device, location, offset, width, verbose=0):
read_32bits = ctypes.c_uint(0);
isRead = cfunc.read_bits(device, location, ctypes.byref(read_32bits), ctypes.c_uint(verbose))
if isRead == -1:
print("An error occured while executing C function read_bits")
return -1
if verbose:
string_32bits = "{:032b}".format(read_32bits.value)
print("Read: %s"%(string_32bits))
mask = 2**width - 1
output = (read_32bits.value>>offset) & mask # convert selected string to integer
if verbose:
print("Unmasked result: %i (%s)"%(output, str(bin(output))))
return output
def WriteProperty(device, location, offset, width, write_value, verbose=0):
read_value = ctypes.c_uint(0);
isRead = cfunc.read_bits(device, location, ctypes.byref(read_value), ctypes.c_uint(verbose))
if isRead == -1:
print("An error occured while executing C function read_bits")
return -1
if verbose:
string_read = "{:032b}".format(read_value.value)
string_write = "{:032b}".format(write_value.value<<offset)
print("Read: %s"%(string_read))
print("Write: %s"%(string_write))
mask = (2**width-1)<<offset
notmask = (2**32-1)-mask
output = ((write_value.value<<offset) & mask) | (read_value.value & notmask)
isWritten = cfunc.write_bits(device, location, output, ctypes.c_uint(verbose))
if isWritten == -1:
print("An error occured while executing C function write_bits.")
return -1
# Readback as checkout
isReadcheck = ctypes.c_uint(cfunc.read_bits(device, location, ctypes.byref(read_value), ctypes.c_uint(verbose) )).value
if isReadcheck == -1:
print("An error occured while executing C function read_bits")
return -1
if isReadcheck == output:
return 0
else:
print("Readback failed. Register not writable.")
print("Check the reading permission for location %s on board %s"%(location, device))
return -1
if __name__ == '__main__':
parser = argparse.ArgumentParser() #Python tool that makes it easy to create an user-friendly command-line interface
parser.add_argument('-b','--board', type=str, help="scouting board", required=True)
parser.add_argument('-a','--action', type=str, help="control action", required=True, choices=actions)
parser.add_argument('-r','--register', type=str, help="control register", required=True)
parser.add_argument('-v','--value', type=str, help="new value", required=False)
parser.add_argument('-f','--filelog', type=str, help="logfile", required=False)
parser.add_argument('-d','--dump', type=int ,help="dump messages", required=False, default=0)
args = parser.parse_args()
board = args.board
reg = args.register
device = config_dict[board]["driver"]
location = config_dict[board]["register"][reg]["location"]
offset = config_dict[board]["register"][reg]["offset"]
width = config_dict[board]["register"][reg]["width"]
action = args.action
value = args.value
verbose = args.dump
filelog = args.filelog
output = 0
# exceptions:
if offset > 31:
print("Offset value %i is out of range 0-30. Check the configuration file."%(offset))
exit()
if width == 0:
print("Width must be grater than 0. Check the configuration file.")
if offset+width > 32:
print("Mask ends out of range. Check the configuration file.")
exit()
if action == "set":
if value == None:
print("action 'set' requires the optional argument --value (-v).")
if filelog:
print("Save log at %s"%(filelog))
f = open(filelog, "w")
f.write("board: %s\n"%(device))
f.write("register: %s\n"%(reg))
f.write("location: %s\n"%(location))
f.write("offset: %i\n"%(offset))
f.write("width: %i\n"%(width))
f.write("action: %s\n"%(action))
f.write("error: action 'set' requires the optional argument --value (-v).")
f.close()
exit()
nbits_allowed = width # number of allowed bits
nbits_write = value.bit_length() # number of bits needed
if nbits_write > nbits_allowed:
print("Overflow error! value %s doesn't fit in the allowed memory location."%(args.value))
if filelog:
print("Save log at %s"%(filelog))
f = open(filelog, "w")
f.write("board: %s\n"%(device))
f.write("register: %s\n"%(reg))
f.write("location: %s\n"%(location))
f.write("offset: %i\n"%(offset))
f.write("width: %i\n"%(width))
f.write("action: %s\n"%(action))
f.write("error: overflow error! value %s doesn't fit in the allowed memory location."%(args.value))
f.close()
exit()
else:
writevalue = ctypes.c_uint(int(value)) #unsigned int (32 bits)
output = WriteProperty(device, location, offset, width, writevalue, verbose=verbose)
if output == -1:
print('The value could not be updated.')
else:
print('Set register %s from location %s on %s: %i'%(reg, location, board, writevalue.value))
elif action == "get":
output = ReadProperty(device, location, offset, width, verbose=verbose)
if output == -1:
print('The register could not be read.')
else:
print('Get register %s from location %s on %s: %i'%(reg, location, board, output))
if filelog:
print("Save log at %s"%(filelog))
f = open(filelog, "w")
f.write("board: %s\n"%(device))
f.write("register: %s\n"%(reg))
f.write("location: %s\n"%(location))
f.write("offset: %i\n"%(offset))
f.write("width: %i\n"%(width))
f.write("action: %s\n"%(action))
f.write("output: %i\n"%(output))
f.close()
Supports Markdown
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