Commit b6a2e5c4 authored by Alessandro Rubini's avatar Alessandro Rubini

on-switch-tests: removed most of them as obsolete

parent 719b76b7
......@@ -133,12 +133,9 @@ editing this file, please add your name in all the proper places.
@item on-switch-tests/
Tests that are meant to be run on the switch itself.
The directory has been copied from @code{software/tests}
as it appeared in the @i{svn} repository; it has not been
recompiled or verified in any way. In this version, only
wr_mon had been made to compile, the other tests still include
@code{build.sh} that sources @code{../../settings}, in the old
way that is now deprecated.
As of March 2012 only a few tests remain, as older ones
only applied to V2, and the switch testing is not a
different project.
@item robustness/
The robustness demo program, copied from @i{svn} and
......
This directory includes tests that are meant to be run on the switch
itself.
This directory used to include tests that are meant to be run on the
switch itself. Now only rtu_test remains, even though it's not
included in the Makefile rules.
The directory has been copied from @code{software/tests} as it
appeared in the @i{svn} repository; it has not been recompiled or
verified in any way. In this version, only wr_mon had been made to
compile, the other tests still include @code{build.sh} that sources
@code{../../settings}, in the old way that is now deprecated.
If you "make" here, only libwripc and wr_mon is compiled.
\ No newline at end of file
If you "make" here, only libwripc and wr_mon are compiled, but
wr_mon must be ported to V3.
CC=$(CROSS_COMPILE)gcc
OBJS = ad9516_test.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = ad9516_test
EXTRAFILES = regs.txt
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run:: all
scp $(OUTPUT) $(EXTRAFILES) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <hw/switch_hw.h>
#define NUM_LEDS 4
uint32_t clkgen_rval(void *clkctl, unsigned int addr);
#define AD9516_MAX_REGS 1024
struct ad9516_regs {
struct {
uint16_t addr;
uint8_t value;
} regs[AD9516_MAX_REGS];
int nregs;
};
int ad9516_load_regset(const char *filename, struct ad9516_regs *regs)
{
FILE *f;
char str[1024], tmp[100];
int start_read = 0, n = 0;
uint32_t addr, val;
f = fopen(filename ,"rb");
if(!f)
{
TRACE(TRACE_ERROR, "can't open AD9516 regset file: %s", filename);
return -1;
}
while(!feof(f))
{
fgets(str, 1024, f);
// printf("%s\n",str);
if(!strncmp(str, "Addr(Hex)", 8)) start_read = 1;
if(start_read)
{
if( sscanf(str, "%04x %08s %02x\n", &addr, tmp, &val) == 3)
{
TRACE(TRACE_INFO, " -> ad9516_reg[0x%x]=0x%x", addr, val);
regs->regs[n].addr = addr;
regs->regs[n].value = val;
n++;
}
}
}
regs->nregs = n;
fclose(f);
return 0;
}
int ad9516_set_state(struct ad9516_regs *regs)
{
int i;
TRACE(TRACE_INFO, "Loading AD9516 state (%d registers)", regs->nregs);
for(i=0;i<regs->nregs;i++)
clkgen_write(NULL, regs->regs[i].addr, regs->regs[i].value);
clkgen_write(NULL, 0x232, 1);
for(i=0;i<regs->nregs;i++)
{
uint8_t v = clkgen_rval(NULL, regs->regs[i].addr);
if(regs->regs[i].value != v) printf("%x:%x/%x\n", regs->regs[i].addr, regs->regs[i].value, v);
}
}
main()
{
char s[2000];
int addr;
int val;
unsigned int i=1;
trace_log_stderr();
shw_init();
ad9516_spi_init();
struct ad9516_regs r;
// shw_pio_set0(PIN_ad9516_refsel);
ad9516_load_regset("/tmp/regs.txt", &r);
ad9516_set_state(&r);
}
#!/bin/sh
. ../../../settings
t=`pwd`
cd ../../libswitchhw
./build.sh clean
./build.sh
cd $t
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
AD9516/17/18 Register Map File, Rev 1.0
Addr(Hex) Value(Bin) Value(Hex)
0000 00011000 18
0001 00000000 00
0002 00010000 10
0003 11000011 C3
0004 00000000 00
0010 01111100 7C
0011 00000001 01
0012 00000000 00
0013 00000110 06
0014 00001000 08
0015 00000000 00
0016 00000100 04
0017 00000000 00
0018 00000111 07
0019 00000000 00
001A 00000000 00
001B 00000000 00
001C 00000110 06
001D 00000000 00
001E 00000000 00
001F 00001110 0E
00A0 00000001 01
00A1 00000000 00
00A2 00000000 00
00A3 00000001 01
00A4 00000000 00
00A5 00000000 00
00A6 00000001 01
00A7 00000000 00
00A8 00000000 00
00A9 00000001 01
00AA 00000000 00
00AB 00000000 00
00F0 00001010 0A
00F1 00001010 0A
00F2 00001010 0A
00F3 00001010 0A
00F4 00001010 0A
00F5 00001000 08
0140 01000010 42
0141 01000010 42
0142 01000010 42
0143 01011010 5A
0190 00000000 00
0191 10000000 80
0192 00000000 00
0193 00110010 32
0194 00000000 00
0195 00000000 00
0196 00110010 32
0197 00000000 00
0198 00000000 00
0199 00110010 32
019A 00000000 00
019B 00010001 11
019C 00100000 20
019D 00000000 00
019E 00110010 32
019F 00000000 00
01A0 00010001 11
01A1 00100000 20
01A2 00000000 00
01A3 00000000 00
01E0 00000000 00
01E1 00000010 02
0230 00000000 00
0231 00000000 00
0232 00000000 00
CC=$(CROSS_COMPILE)gcc
OBJS = blink_leds.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = blink_leds
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <hw/switch_hw.h>
#define NUM_LEDS 8
main()
{
unsigned int i=0,di=1,previ=0;
trace_log_stderr();
shw_request_fpga_firmware(FPGA_ID_MAIN, "board_test");
shw_init();
for(;;)
{
shw_set_fp_led(previ, LED_OFF);
shw_set_fp_led(i, LED_GREEN);
usleep(30000);
shw_set_fp_led(i, LED_RED);
usleep(30000);
previ=i;
i+=di;
if(i == 0 || i==(NUM_LEDS-1)) di=-di;
}
}
#!/bin/sh
. ../../../settings
#cd ../../libswitchhw
#./build.sh
#cd ../tests/blink_leds
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = calibrator_test.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include
OUTPUT = calibrator_test
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) ../../drivers/bin/*.ko root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
make CROSS_COMPILE=$CROSS_COMPI_CPU $1 $2 $3 $4
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/time.h>
#include <signal.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
#include <hw/minic_regs.h>
#include <hw/endpoint_regs.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
//#include <net/if.h>
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/net_tstamp.h>
#include <linux/sockios.h>
#include <linux/errqueue.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#include <hw/dmtd_calibrator_regs.h>
#include <hw/endpoint_regs.h>
#include <hw/phy_calibration.h>
main()
{
int i, rval;
system("/sbin/rmmod /tmp/wr_minic.ko");
system("/sbin/rmmod /tmp/wr_vic.ko");
trace_log_stderr();
shw_init();
system("/sbin/insmod /tmp/wr_vic.ko");
system("/sbin/insmod /tmp/wr_minic.ko");
system("/sbin/ifconfig wru1 hw ether 00:50:fc:96:9b:0e");
system("/sbin/ifconfig wru1 up 192.168.100.100");
_fpga_writel(FPGA_BASE_MINIC_UP0 + (1<<14) + EP_REG_PHIO, EP_PHIO_ENABLE);
_fpga_writel(FPGA_BASE_MINIC_UP1 + (1<<14) + EP_REG_PHIO, EP_PHIO_ENABLE);
shw_hpll_switch_reference("wru1");
while(!shw_hpll_check_lock());
shw_dmpll_switch_reference("wru1");
while(!shw_dmpll_check_lock());
shw_cal_enable_feedback("wru1", 1, PHY_CALIBRATE_RX);
double phase_rx;
for(;;)
{
while(!(rval = shw_cal_measure(&phase_rx)));
if(rval < 0)
{
printf("error measuring RX delay\n");
return -1;
}
printf("rval = %d, deltaRX(uncorrected) = %.3f ns\n", rval, phase_rx);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
void clear_screen()
{
printf("\033[2J\033[1;1H");
}
\ No newline at end of file
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = dmpll_test.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include
OUTPUT = dmpll_test
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) ../../drivers/bin/*.ko root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <hw/dmpll_regs.h>
int sign_extend(uint32_t val, int nbits)
{
if(val & (1<<(nbits-1))) return (0xffffffff ^ ((1<<nbits)-1)) | val; else return val;
}
main(int argc, char *argv[])
{
if(argc < 3) return -1;
FILE *fin, *fout;
uint32_t r0, r1,r2,r3;
int npoints;
int i = 0;
fin = fopen(argv[1], "rb");
fout = fopen(argv[2], "wb");
npoints = atoi(argv[3]);
while(!feof(fin) && (++i < npoints))
{
fread(&r0, 4, 1, fin);
fread(&r1, 4, 1, fin);
fread(&r2, 4, 1, fin);
fread(&r3, 4, 1, fin);
fprintf(fout, "%d %d %d %d\n", i,
sign_extend(DMPLL_RFIFO_R0_ERR_VAL_R(r0), 18),
DMPLL_RFIFO_R3_DAC_VAL_R(r3),
// DMPLL_RFIFO_R1_TAG_REF_R(r1) - DMPLL_RFIFO_R2_TAG_FB_R(r2),
r0 & DMPLL_RFIFO_R2_FP_MODE ? 60000 : 0);
}
}
\ No newline at end of file
#include <stdio.h>
#include <inttypes.h>
#include <sys/time.h>
#include <signal.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
#include <hw/dmpll_regs.h>
#define MAX_MEAS 120000
#define DMPLL_CHANNEL_LOCAL 0
#define DMPLL_CHANNEL_UP0 1
#define DMPLL_CHANNEL_UP1 2
uint32_t rec_buf[MAX_MEAS * 4];
int n_meas = 0;
static void dmpll_purge_rfifo()
{
for(;;)
{
shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_R0);
}
}
static void dmpll_poll_rfifo()
{
for(;;)
{
if(shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_CSR) & DMPLL_RFIFO_CSR_EMPTY) return;
if(n_meas < MAX_MEAS) {
rec_buf[4*n_meas] = shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_R0);
rec_buf[4*n_meas+1] = shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_R1);
rec_buf[4*n_meas+2] = shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_R2);
rec_buf[4*n_meas+3] = shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_RFIFO_R3);
n_meas++;
}
}
}
static void dmpll_setup_deglitcher(uint32_t reg, int hi, int lo, int glitch)
{
shw_clkb_write_reg(CLKB_BASE_DMPLL + reg, DMPLL_DGCR_IN0_THR_HI_W(hi) |
DMPLL_DGCR_IN0_THR_LO_W(lo) |
DMPLL_DGCR_IN0_THR_GLITCH_W(glitch));
}
static void dmpll_set_phase_shift(int channel, int ps_shift)
{
switch(channel)
{
#if 0
case DMPLL_CHANNEL_LOCAL:
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_LOCAL, ps_shift);
break;
case DMPLL_CHANNEL_UP0:
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_0, ps_shift);
break;
#endif
case DMPLL_CHANNEL_UP1:
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_IN0, ps_shift);
break;
}
}
static int dmpll_shifter_busy(int channel)
{
switch(channel)
{
/* case DMPLL_CHANNEL_LOCAL:
return shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_LOCAL) & (1<<31);
case DMPLL_CHANNEL_UP0:
return shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_UP0) & (1<<31);*/
case DMPLL_CHANNEL_UP1:
return shw_clkb_read_reg(CLKB_BASE_DMPLL + DMPLL_REG_PSCR_IN0) & DMPLL_PSCR_IN0_BUSY;
}
return 0;
}
void sighandler(int sig)
{
fprintf(stderr,"Saving: %d", n_meas);
FILE *f=fopen("/tmp/dmpll_meas.dat","wb");
fwrite(rec_buf, 8, n_meas, f);
fclose(f);
exit(0);
}
main()
{
int i;
int ps_shift = 16000;
int ps_new_shift = 0;
trace_log_stderr();
shw_init();
printf("Waiting for Helper PLL lock...\n");
while(!shw_hpll_check_lock()) usleep(10000);
/*
for(i=0;i<30;i++)
{
shw_hpll_update(); usleep(100000);
}*/
printf("Initializing the DMPLL.\n");
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PCR, 0);
dmpll_setup_deglitcher(DMPLL_REG_DGCR_IN0, 150, 150, 60);
dmpll_setup_deglitcher(DMPLL_REG_DGCR_FB, 150, 150, 60);
// gain
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_FBGR, DMPLL_FBGR_F_KP_W(100) | DMPLL_FBGR_F_KI_W(600));
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PBGR, DMPLL_PBGR_P_KP_W(-2000) | DMPLL_PBGR_P_KI_W(-40));
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_LDCR, DMPLL_LDCR_LD_THR_W(300) | DMPLL_LDCR_LD_SAMP_W(2000));
fprintf(stderr,"X=exit\n");
dmpll_purge_rfifo();
fprintf(stderr,"X=exit\n");
shw_clkb_write_reg(CLKB_BASE_DMPLL + DMPLL_REG_PCR, DMPLL_PCR_ENABLE | DMPLL_PCR_REFSEL_W(0) | DMPLL_PCR_DAC_CLKSEL_W(2) | DMPLL_PCR_PS_SPEED_W(100) | DMPLL_PCR_SWRST);
//term_init();
// signal(SIGINT, sighandler);
//signal(SIGTERM, sighandler);
//signal(SIGKILL, sighandler);
fprintf(stderr,"X=exit\n");
dmpll_set_phase_shift(DMPLL_CHANNEL_UP1, 16400);
for(;;)
{
/* int c=term_get();
if(c=='x') break;
if(c=='a') { ps_shift += 200; ps_new_shift = 1; }
if(c=='z') { ps_shift -= 200; ps_new_shift = 1; }
// uint32_t psr = shw_clkb_read_reg(CLKB_BASE_DMPLL+ DMPLL_REG_PSR);
// fprintf(stderr,"PhLk: %d FrLk: %d\n", psr & DMPLL_PSR_PHASE_LK ? 1 : 0, psr & DMPLL_PSR_FREQ_LK ? 1 : 0);
if(ps_new_shift)// && !dmpll_shifter_busy(DMPLL_CHANNEL_UP1))
{
fprintf(stderr,"Setting PS = %d\n", ps_shift);
ps_new_shift = 0;
dmpll_set_phase_shift(DMPLL_CHANNEL_UP1, ps_shift);
}
*/
// dmpll_poll_rfifo();
}
//term_restore();
}
#!/bin/bash
IP=192.168.1.6
scp root@$IP:/tmp/dmpll_meas.dat ./
gcc convert_meas.c -o convert_meas -I../../include
./convert_meas dmpll_meas.dat dmpll_plotdata.dat 40000
gnuplot -e "set xlabel 'time'; set y2label 'DAC value'; set ylabel 'Phase/freq error'; set yrange [-10000:10000]; set y2range [0:65540]; plot 'dmpll_plotdata.dat' using 1:2 title 'Phase/freq error' with lines axis x1y1, \
'dmpll_plotdata.dat' using 1:3 title 'DAC drive' with lines axis x1y2, \
'dmpll_plotdata.dat' using 1:4 title 'Freq/Phase mode' with lines axis x1y2; \
"
#, plot "dmpll_plotdata.dat" using 1:3 title "integral value" with lines, plot "dmpll_plotdata.dat" using 1:4 title "DAC drive" with lines'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = ep_stats.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw -L../../libwripc -L../../libptpnetif -lwripc -lptpnetif
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include -I../../libptpnetif -I../../wrsw_hal -I../../libwripc -g
OUTPUT = ep_stats
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
- scp $(OUTPUT) root@192.168.1.6:/tmp
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hw/fpga_regs.h>
#include <hw/endpoint_regs.h>
#include <hal_client.h>
#define RTU_BANK_SIZE 65536
static const struct {
char name[5];
uint32_t base_addr;
} endpoints_map[]= {
{"wru0", FPGA_BASE_MINIC_UP0 + 0x4000},
{"wru1", FPGA_BASE_MINIC_UP1 + 0x4000},
{NULL, 0}
};
static const struct {
char name[64];
int offset;
} rmon_counters[] = {
{"RX PCS sync lost events", 0},
{"RX PCS invalid 8b10b codes", 1},
{"RX PCS FIFO overruns", 2},
{"TX PCS FIFO underruns", 3},
{"RX CRC errors", 4},
{"RX valid frames", 5},
{"RX runt frames", 6},
{"RX giant frames",7},
{"RX errors reported by PCS", 8},
{"RX buffer drops", 9},
{"Received PAUSEs", 10},
{"Sent PAUSEs", 11},
{NULL, 0},
};
int show_stats(char *if_name)
{
uint32_t base_addr = 0;
int i;
for(i=0; endpoints_map[i].name; i++)
if(!strcmp(endpoints_map[i].name, if_name))
{
base_addr = endpoints_map[i].base_addr;
break;
}
if(!base_addr) return -1;
printf("\033[2J\033[1;1H");
printf("Stats for interface: %s\n-----------------------\n\n", if_name);
for(i=0;i<12;i++)
printf("%-40s: %d\n", rmon_counters[i].name, _fpga_readl(base_addr + 0x80 + rmon_counters[i].offset * 4));
return 0;
}
void init()
{
if(halexp_client_init() < 0)
{
printf("Oops... Looks like the HAL is not running :( \n\n");
exit(-1);
}
shw_fpga_mmap_init();
}
main(int argc, char *argv[])
{
init();
for(;;)
{
if(show_stats(argv[1]) < 0)
break;
usleep(100000);
}
return 0;
}
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
"Norma Jean"
"/home/wrdev/WR_buildroot/WR_Switch/fpgaboot/mblaster.c" 1217
nil
nil
CC=$(CROSS_COMPILE)gcc
OBJS = cpu_io.o mb_io.o mblaster.o main.o
CFLAGS = -I. -O3
OUTPUT = fpgaboot
all: $(OBJS)
${CC} -s -o $(OUTPUT) $(OBJS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
install-image:
cp $(OUTPUT) ../root/usr/sbin
install: all
scp $(OUTPUT) root@192.168.1.2:/root
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
/*
* arch/arm/mach-at91/include/mach/at91_pio.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* Parallel I/O Controller (PIO) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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 AT91_PIO_H
#define AT91_PIO_H
#define PIO_PER 0x00 /* Enable Register */
#define PIO_PDR 0x04 /* Disable Register */
#define PIO_PSR 0x08 /* Status Register */
#define PIO_OER 0x10 /* Output Enable Register */
#define PIO_ODR 0x14 /* Output Disable Register */
#define PIO_OSR 0x18 /* Output Status Register */
#define PIO_IFER 0x20 /* Glitch Input Filter Enable */
#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */
#define PIO_IFSR 0x28 /* Glitch Input Filter Status */
#define PIO_SODR 0x30 /* Set Output Data Register */
#define PIO_CODR 0x34 /* Clear Output Data Register */
#define PIO_ODSR 0x38 /* Output Data Status Register */
#define PIO_PDSR 0x3c /* Pin Data Status Register */
#define PIO_IER 0x40 /* Interrupt Enable Register */
#define PIO_IDR 0x44 /* Interrupt Disable Register */
#define PIO_IMR 0x48 /* Interrupt Mask Register */
#define PIO_ISR 0x4c /* Interrupt Status Register */
#define PIO_MDER 0x50 /* Multi-driver Enable Register */
#define PIO_MDDR 0x54 /* Multi-driver Disable Register */
#define PIO_MDSR 0x58 /* Multi-driver Status Register */
#define PIO_PUDR 0x60 /* Pull-up Disable Register */
#define PIO_PUER 0x64 /* Pull-up Enable Register */
#define PIO_PUSR 0x68 /* Pull-up Status Register */
#define PIO_ASR 0x70 /* Peripheral A Select Register */
#define PIO_BSR 0x74 /* Peripheral B Select Register */
#define PIO_ABSR 0x78 /* AB Status Register */
#define PIO_OWER 0xa0 /* Output Write Enable Register */
#define PIO_OWDR 0xa4 /* Output Write Disable Register */
#define PIO_OWSR 0xa8 /* Output Write Status Register */
#endif
/*
* arch/arm/mach-at91/include/mach/at91_pmc.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* Power Management Controller (PMC) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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 AT91_PMC_H
#define AT91_PMC_H
#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */
#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */
#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */
#define AT91_PMC_PCK (1 << 0) /* Processor Clock */
#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */
#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock Enable [some SAM9 only] */
#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */
#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */
#define AT91CAP9_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91CAP9 only] */
#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */
#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */
#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */
#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */
#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */
#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */
#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */
#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */
#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */
#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [some SAM9, CAP9] */
#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */
#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */
#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */
#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */
#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register [not on SAM9RL] */
#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */
#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass [SAM9x, CAP9] */
#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */
#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */
#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */
#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */
#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */
#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */
#define AT91_PMC_DIV (0xff << 0) /* Divider */
#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */
#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */
#define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */
#define AT91_PMC_USBDIV_1 (0 << 28)
#define AT91_PMC_USBDIV_2 (1 << 28)
#define AT91_PMC_USBDIV_4 (2 << 28)
#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */
#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */
#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
#define AT91_PMC_CSS_SLOW (0 << 0)
#define AT91_PMC_CSS_MAIN (1 << 0)
#define AT91_PMC_CSS_PLLA (2 << 0)
#define AT91_PMC_CSS_PLLB (3 << 0)
#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */
#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
#define AT91_PMC_PRES_1 (0 << 2)
#define AT91_PMC_PRES_2 (1 << 2)
#define AT91_PMC_PRES_4 (2 << 2)
#define AT91_PMC_PRES_8 (3 << 2)
#define AT91_PMC_PRES_16 (4 << 2)
#define AT91_PMC_PRES_32 (5 << 2)
#define AT91_PMC_PRES_64 (6 << 2)
#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */
#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */
#define AT91RM9200_PMC_MDIV_2 (1 << 8)
#define AT91RM9200_PMC_MDIV_3 (2 << 8)
#define AT91RM9200_PMC_MDIV_4 (3 << 8)
#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9,CAP9 only] */
#define AT91SAM9_PMC_MDIV_2 (1 << 8)
#define AT91SAM9_PMC_MDIV_4 (2 << 8)
#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */
#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */
#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */
#define AT91_PMC_PDIV_1 (0 << 12)
#define AT91_PMC_PDIV_2 (1 << 12)
#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */
#define AT91_PMC_PLLADIV2_OFF (0 << 12)
#define AT91_PMC_PLLADIV2_ON (1 << 12)
#define AT91_PMC_USB (AT91_PMC + 0x38) /* USB Clock Register [some SAM9 only] */
#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
#define AT91_PMC_USBS_PLLA (0 << 0)
#define AT91_PMC_USBS_UPLL (1 << 0)
#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */
#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */
#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */
#define AT91_PMC_CSSMCK_CSS (0 << 8)
#define AT91_PMC_CSSMCK_MCK (1 << 8)
#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */
#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */
#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */
#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9, AT91CAP9 only] */
#define AT91_PMC_OSCSEL (1 << 7) /* Slow Clock Oscillator [AT91CAP9 revC only] */
#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */
#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */
#define AT91_PMC_PROT (AT91_PMC + 0xe4) /* Protect Register [AT91CAP9 revC only] */
#define AT91_PMC_PROTKEY 0x504d4301 /* Activation Code */
#define AT91_PMC_VER (AT91_PMC + 0xfc) /* PMC Module Version [AT91CAP9 only] */
#endif
/*
* arch/arm/mach-at91/include/mach/at91sam9263.h
*
* (C) 2007 Atmel Corporation.
*
* Common definitions.
* Based on AT91SAM9263 datasheet revision B (Preliminary).
*
* 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 AT91SAM9263_H
#define AT91SAM9263_H
/*
* Peripheral identifiers/interrupts.
*/
#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
#define AT91_ID_SYS 1 /* System Peripherals */
#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */
#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */
#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */
#define AT91SAM9263_ID_US0 7 /* USART 0 */
#define AT91SAM9263_ID_US1 8 /* USART 1 */
#define AT91SAM9263_ID_US2 9 /* USART 2 */
#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */
#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */
#define AT91SAM9263_ID_CAN 12 /* CAN */
#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */
#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */
#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */
#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */
#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */
#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */
#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */
#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */
#define AT91SAM9263_ID_EMAC 21 /* Ethernet */
#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */
#define AT91SAM9263_ID_UDP 24 /* USB Device Port */
#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */
#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */
#define AT91SAM9263_ID_DMA 27 /* DMA Controller */
#define AT91SAM9263_ID_UHP 29 /* USB Host port */
#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */
#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */
/*
* User Peripheral physical base addresses.
*/
#define AT91SAM9263_BASE_UDP 0xfff78000
#define AT91SAM9263_BASE_TCB0 0xfff7c000
#define AT91SAM9263_BASE_TC0 0xfff7c000
#define AT91SAM9263_BASE_TC1 0xfff7c040
#define AT91SAM9263_BASE_TC2 0xfff7c080
#define AT91SAM9263_BASE_MCI0 0xfff80000
#define AT91SAM9263_BASE_MCI1 0xfff84000
#define AT91SAM9263_BASE_TWI 0xfff88000
#define AT91SAM9263_BASE_US0 0xfff8c000
#define AT91SAM9263_BASE_US1 0xfff90000
#define AT91SAM9263_BASE_US2 0xfff94000
#define AT91SAM9263_BASE_SSC0 0xfff98000
#define AT91SAM9263_BASE_SSC1 0xfff9c000
#define AT91SAM9263_BASE_AC97C 0xfffa0000
#define AT91SAM9263_BASE_SPI0 0xfffa4000
#define AT91SAM9263_BASE_SPI1 0xfffa8000
#define AT91SAM9263_BASE_CAN 0xfffac000
#define AT91SAM9263_BASE_PWMC 0xfffb8000
#define AT91SAM9263_BASE_EMAC 0xfffbc000
#define AT91SAM9263_BASE_ISI 0xfffc4000
#define AT91SAM9263_BASE_2DGE 0xfffc8000
#define AT91_BASE_SYS 0xffffe000
/*
* System Peripherals (offset from AT91_BASE_SYS)
*/
#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS)
#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS)
#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS)
#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS)
#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS)
#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS)
#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS)
#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS)
#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS)
#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS)
#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS)
#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS)
#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS)
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91_USART0 AT91SAM9263_BASE_US0
#define AT91_USART1 AT91SAM9263_BASE_US1
#define AT91_USART2 AT91SAM9263_BASE_US2
#define AT91_SMC AT91_SMC0
/*
* Internal Memory.
*/
#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */
#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */
#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */
#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */
#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */
#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */
#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */
#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */
#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */
#endif
#!/bin/sh
. ../../../settings
make CROSS_COMPILE=$CC_CPU $1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <fcntl.h>
#include "cpu_io.h"
static volatile uint8_t *sys_base;
static volatile uint8_t *pio_base[NUM_PIO_BANKS];
int io_init()
{
int fd = open("/dev/mem", O_RDWR);
if(!fd) return -1;
sys_base = mmap(NULL, 0x2000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, AT91_BASE_SYS);
if(sys_base == NULL)
{
perror("mmap()");
close(fd);
return -1;
}
// fprintf(stderr,"AT91_SYS mmapped to: 0x%08x\n", sys_base);
pio_base[0] = sys_base + AT91_PIOA;
pio_base[1] = sys_base + AT91_PIOB;
pio_base[2] = sys_base + AT91_PIOC;
pio_base[3] = sys_base + AT91_PIOD;
pio_base[4] = sys_base + AT91_PIOE;
return 0;
}
void pio_set_state(int port, int pin, int state)
{
if(state)
_writel(pio_base[port] + PIO_SODR, (1<<pin))
else
_writel(pio_base[port] + PIO_CODR, (1<<pin))
}
void pio_set_mode(int port, int pin, int mode, int dir)
{
_writel(pio_base[port] + PIO_IDR, (1<<pin)); // disable irq
if(mode & PIN_MODE_PULLUP)
_writel(pio_base[port] + PIO_PUER, (1<<pin)) // enable pullup
else
_writel(pio_base[port] + PIO_PUDR, (1<<pin)) // disable pullup
switch(mode & 0x3)
{
case PIN_MODE_GPIO:
_writel(pio_base[port] + PIO_PER, (1<<pin)); // enable gpio mode
break;
case PIN_MODE_PERIPH_A:
_writel(pio_base[port] + PIO_PDR, (1<<pin)); // disable gpio mode
_writel(pio_base[port] + PIO_ASR, (1<<pin)); // select peripheral A
break;
case PIN_MODE_PERIPH_B:
_writel(pio_base[port] + PIO_PDR, (1<<pin)); // disable gpio mode
_writel(pio_base[port] + PIO_BSR, (1<<pin)); // select peripheral B
break;
}
if(dir)
_writel(pio_base[port] + PIO_OER, (1<<pin)) // select output
else
_writel(pio_base[port] + PIO_ODR, (1<<pin)); // select input
}
static const struct {
int port;
int pin;
int mode;
} pck_port_mapping[] =
{
{PIOA, 13, PIN_MODE_PERIPH_B},
{PIOB, 10, PIN_MODE_PERIPH_B},
{PIOA, 6, PIN_MODE_PERIPH_B},
{PIOE, 11, PIN_MODE_PERIPH_B}
};
int pck_enable(int pck_num, int prescaler, int source)
{
if(pck_num > 3) return -1;
pio_set_mode(pck_port_mapping[pck_num].port, pck_port_mapping[pck_num].pin, pck_port_mapping[pck_num].mode, 1);
_writel(sys_base + AT91_PMC_PCKR(pck_num), source | prescaler);
// enable the PCK output
_writel(sys_base + AT91_PMC_SCER, (1<< (8+pck_num)));
return 0;
}
int pio_get_state(int port, int pin)
{
return (_readl(pio_base[port] + PIO_PDSR) & (1<<pin)) ? 1: 0;
}
volatile uint8_t *io_get_sys_base()
{
return sys_base;
}
volatile uint8_t *pio_get_port_addr(int port)
{
return pio_base[port];
}
#ifndef __CPU_IO_H
#define __CPU_IO_H
#include <sys/types.h>
#include <inttypes.h>
#include <at91/at91sam9263.h>
#include <at91/at91_pio.h>
#include <at91/at91_pmc.h>
#define NUM_PIO_BANKS 5
#define PIOA 0
#define PIOB 1
#define PIOC 2
#define PIOD 3
#define PIOE 4
#define PIN_MODE_GPIO 0
#define PIN_MODE_PERIPH_A 1
#define PIN_MODE_PERIPH_B 2
#define PIN_MODE_PULLUP 0x80
#define _writel(reg, val){ *(volatile uint32_t *)(reg) = (val); }
#define _readl(reg) (*(volatile uint32_t *)(reg))
int io_init();
void pio_set_state(int port, int pin, int state);
void pio_set_mode(int port, int pin, int mode, int dir);
int pck_enable(int pck_num, int prescaler, int source);
int pio_get_state(int port, int pin);
volatile uint8_t *io_get_sys_base();
volatile uint8_t *pio_get_port_addr(int port);
#endif
#include <stdio.h>
#include <unistd.h>
#include "cpu_io.h"
#include "mb_io.h"
#define N_LEDS 8
struct {
int port;
int pin;
} leds[] = {
{PIOC, 5},
{PIOC, 12},
{PIOC, 7},
{PIOC, 19},
{PIOC, 9},
{PIOC, 17},
{PIOC, 14},
{PIOC, 6},
{0, 0}
};
void blink_leds()
{
int i;
for(i=0;i<N_LEDS;i++)
pio_set_mode(leds[i].port, leds[i].pin, PIN_MODE_GPIO, 1);
i=0;
for(;;)
{
int prevled=((i-1)<0)?(N_LEDS-1):i-1;
pio_set_state(leds[prevled].port, leds[prevled].pin, 0);
pio_set_state(leds[i].port, leds[i].pin, 1);
i++; if(i>=N_LEDS) i = 0;
usleep(100000);
}
}
extern int mblaster_boot_fpga(const char *filename, int fpga_sel);
main(int argc, char *argv[])
{
int fpga_sel = -1;
io_init();
pck_enable(0, AT91_PMC_CSS_PLLA, AT91_PMC_PRES_2);
if(argc<3)
{
fprintf(stderr,"Usage: %s <bitstream_file> <MAIN/CLKB>\n\n",argv[0]);
return -1;
}
if(!strcasecmp(argv[2], "main"))
fpga_sel = FPGA_MAIN;
else if(!strcasecmp(argv[2], "clkb"))
fpga_sel = FPGA_CLKB;
fprintf(stderr,"FPGAsel: %d\n", fpga_sel);
mblaster_boot_fpga(argv[1], fpga_sel);
return 0;
}
/****************************************************************************/
/* */
/* Module: mb_io.c (MicroBlaster) */
/* */
/* Copyright (C) Altera Corporation 2004 */
/* */
/* Descriptions: Defines all IO control functions. operating system */
/* is defined here. Functions are operating system */
/* dependant. */
/* */
/* Revisions: 1.0 12/10/01 Sang Beng Ng */
/* Supports Altera ByteBlaster hardware download cable */
/* on Windows NT. */
/* 1.1 05/28/04 Chuin Tein Ong */
/* Supports both Altera ByteBlaster II and ByteBlaster MV */
/* download cables on Windows NT. */
/* */
/****************************************************************************/
#include "mb_io.h"
#include <stdio.h>
int fopen_rbf( char argv[], char* mode)
{
FILE* file_id;
file_id = fopen( argv, mode );
return (int) file_id;
}
int fclose_rbf( int file_id)
{
fclose( (FILE*) file_id);
return 0;
}
int fseek_rbf( int finputid, int start, int end )
{
int seek_position;
seek_position = fseek( (FILE*) finputid, start, end );
return seek_position;
}
int ftell_rbf( int finputid )
{
int file_size;
file_size = ftell( (FILE*) finputid );
return file_size;
}
int fgetc_rbf( int finputid )
{
int one_byte;
one_byte = fgetc( (FILE*) finputid );
return one_byte;
}
void delay ( int factor)
{
int i;
for (i=0;i<factor;i++) asm volatile("nop");
}
\ No newline at end of file
/****************************************************************************/
/* */
/* Module: mb_io.h (MicroBlaster) */
/* */
/* Copyright (C) Altera Corporation 2004 */
/* */
/* Descriptions: Defines all IO control functions. operating system */
/* is defined here. Functions are operating system */
/* dependant. */
/* */
/* Revisions: 1.0 12/10/01 Sang Beng Ng */
/* Supports Altera ByteBlaster hardware download cable */
/* on Windows NT. */
/* 1.1 05/28/04 Chuin Tein Ong */
/* Supports both Altera ByteBlaster II and ByteBlaster MV */
/* download cables on Windows NT. */
/* */
/****************************************************************************/
#ifndef INC_MB_IO_H
#define INC_MB_IO_H
#define EMBEDDED 2
/*///////////////////////*/
/* Functions Prototyping */
/*///////////////////////*/
int ReadByteBlaster ( int port );
void WriteByteBlaster ( int port, int data, int test );
#define FPGA_MAIN 0
#define FPGA_CLKB 1
#endif /* INC_MB_IO_H */
#include "mb_io.h"
#include <stdio.h>
#include "cpu_io.h"
#define SIG_DCLK 0
#define SIG_NCONFIG 1
#define SIG_DATA0 2
#define SIG_NSTATUS 3
#define SIG_CONFDONE 4
#define S_CUR 1
#define S_END 2
#define S_SET 0
#define INIT_CYCLE 50
#define RECONF_COUNT_MAX 5
#define CHECK_EVERY_X_BYTE 10240
#define CLOCK_X_CYCLE 0
static inline int CheckSignal ( int signal );
static inline void Dump2Port ( int signal, int data, int clk );
void PrintError ( int configuration_count );
void ProcessFileInput ( int finputid );
static inline void ProgramByte ( int one_byte );
void SetPortMode ( int mode );
const char VERSION[4] = "1.1";
struct pgm_io_mapping {
int port;
int pin;
int mode;
int dir;
int invert;
};
static const struct pgm_io_mapping io_mapping_main [] = {
{ PIOB, 1, PIN_MODE_GPIO, 1, 0}, // SIG_DCLK
{ PIOB, 22, PIN_MODE_GPIO, 1, 0}, // SIG_NCONFIG
{ PIOB, 2, PIN_MODE_GPIO, 1, 0}, // SIG_DATA0
{ PIOB, 31, PIN_MODE_GPIO, 0, 0}, // SIG_NSTATUS
{ PIOB, 18, PIN_MODE_GPIO, 0, 1} // SIG_CONFDONE
};
static const struct pgm_io_mapping io_mapping_clkb [] = {
{ PIOB, 7, PIN_MODE_GPIO, 1, 0}, // SIG_DCLK
{ PIOB, 23, PIN_MODE_GPIO, 1, 0}, // SIG_NCONFIG
{ PIOB, 8, PIN_MODE_GPIO, 1, 0}, // SIG_DATA0
{ PIOB, 28, PIN_MODE_GPIO, 0, 0}, // SIG_NSTATUS
{ PIOB, 24, PIN_MODE_GPIO, 0, 1} // SIG_CONFDONE
};
struct {
volatile uint8_t *port_in;
volatile uint8_t *port_1;
volatile uint8_t *port_0;
uint32_t mask;
uint32_t xorval;
} fast_io_map[5];
void port_init(struct pgm_io_mapping *io_mapping)
{
int i;
for(i=0; i<5; i++)
{
pio_set_state(io_mapping[i].port, io_mapping[i].pin, 1);
pio_set_mode(io_mapping[i].port, io_mapping[i].pin, io_mapping[i].mode, io_mapping[i].dir);
fast_io_map[i].port_in = pio_get_port_addr(io_mapping[i].port) + PIO_PDSR;
fast_io_map[i].port_0 = pio_get_port_addr(io_mapping[i].port) + PIO_CODR;
fast_io_map[i].port_1 = pio_get_port_addr(io_mapping[i].port) + PIO_SODR;
fast_io_map[i].mask = (1 << io_mapping[i].pin);
fast_io_map[i].xorval = io_mapping[i].invert ? (1 << io_mapping[i].pin) : 0;
}
}
int mblaster_boot_fpga(const char *filename, int fpga_sel)
{
int file_id;
if(fpga_sel == FPGA_MAIN)
port_init(io_mapping_main);
else if(fpga_sel == FPGA_CLKB)
port_init(io_mapping_clkb);
else {
fprintf( stderr, "Error: please select either MAIN or CLKB FPGA.", filename );
return -1;
}
file_id = fopen_rbf( filename, "rb" );
if ( file_id )
fprintf( stdout, "Info: Programming file: \"%s\" opened...\n", filename );
else
{
fprintf( stderr, "Error: Could not open programming file: \"%s\"\n", filename );
return -1;
}
ProcessFileInput( file_id );
if ( file_id )
fclose_rbf(file_id);
return 0;
}
/********************************************************************************/
/* Name: ProcessFileInput */
/* */
/* Parameters: FILE* finputid */
/* - programming file pointer. */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Get programming file size, parse through every single byte */
/* and dump to parallel port. */
/* */
/* Configuration Hardware is verified before configuration */
/* starts. */
/* */
/* For every [CHECK_EVERY_X_BYTE] bytes, NSTATUS pin is */
/* checked for error. When the file size reached, CONF_DONE */
/* pin is checked for configuration status. Then, another */
/* [INIT_CYCLE] clock cycles are dumped while initialization */
/* is in progress. */
/* */
/* Configuration process is restarted whenever error found. */
/* The maximum number of auto-reconfiguration is */
/* [RECONF_COUNT_MAX]. */
/* */
/********************************************************************************/
void ProcessFileInput( int finputid )
{
int program_done = 0; /* programming process (configuration and initialization) done = 1 */
int seek_position = 0; /* file pointer position */
long int file_size = 0; /* programming file size */
int configuration_count = RECONF_COUNT_MAX; /* # reprogramming after error */
int one_byte = 0; /* the byte to program */
long int i = 0; /* standard counter variable */
int confdone_ok = 1; /* CONF_DONE pin. '1' - error */
int nstatus_ok = 0; /* NSTATUS pin. '0' - error */
int clock_x_cycle = CLOCK_X_CYCLE; /* Clock another 'x' cycles during user mode ( not necessary, for debug purpose only) */
int BBMV=0;
int BBII=0;
/* Get file size */
seek_position = fseek_rbf( finputid, 0, S_END );
if ( seek_position )
{
fprintf( stderr, "Error: End of file could not be located!" );
return;
}
file_size = ftell_rbf( finputid );
fprintf( stdout, "Info: Programming file size: %ld\n", file_size );
/* Start configuration */
while ( !program_done && (configuration_count>0) )
{
/* Reset file pointer and parallel port registers */
fseek_rbf( finputid, 0, S_SET );
fprintf( stdout, "\n***** Start configuration process *****\nPlease wait...\n" );
/* Drive a transition of 0 to 1 to NCONFIG to indicate start of configuration */
Dump2Port( SIG_NCONFIG, 0, 0 );
Dump2Port( SIG_NCONFIG, 1, 0 );
/* Loop through every single byte */
for ( i = 0; i < file_size; i++ )
{
/*one_byte = fgetc( (FILE*) finputid );*/
one_byte = fgetc_rbf( finputid );
/* Progaram a byte */
ProgramByte( one_byte );
/* Check for error through NSTATUS for every 10KB programmed and the last byte */
if ( !(i % CHECK_EVERY_X_BYTE) || (i == file_size - 1) )
{
nstatus_ok = CheckSignal( SIG_NSTATUS );
if ( !nstatus_ok )
{
PrintError( configuration_count-1 );
program_done = 0;
break;
}
else
program_done = 1;
}
}
configuration_count--;
if ( !program_done )
continue;
/* Configuration end */
/* Check CONF_DONE that indicates end of configuration */
confdone_ok = CheckSignal( SIG_CONFDONE );
if ( confdone_ok )
{
fprintf( stderr, "Error: Configuration done but contains error... CONF_DONE is %s\n", (confdone_ok? "LOW":"HIGH") );
program_done = 0;
PrintError( configuration_count );
if ( configuration_count == 0 )
break;
}
/* if contain error during configuration, restart configuration */
if ( !program_done )
continue;
/* program_done = 1; */
/* Start initialization */
/* Clock another extra DCLK cycles while initialization is in progress
through internal oscillator or driving clock cycles into CLKUSR pin */
/* These extra DCLK cycles do not initialize the device into USER MODE */
/* It is not required to drive extra DCLK cycles at the end of
configuration */
/* The purpose of driving extra DCLK cycles here is to insert some delay
while waiting for the initialization of the device to complete before
checking the CONFDONE and NSTATUS signals at the end of whole
configuration cycle */
for ( i = 0; i < INIT_CYCLE; i++ )
{
Dump2Port( SIG_DCLK, 0, 0 );
Dump2Port( SIG_DCLK, 1, 0 );
}
/* Initialization end */
nstatus_ok = CheckSignal( SIG_NSTATUS );
confdone_ok = CheckSignal( SIG_CONFDONE );
if ( !nstatus_ok || confdone_ok )
{
fprintf( stderr, "Error: Initialization finish but contains error: NSTATUS is %s and CONF_DONE is %s. Exiting...", (nstatus_ok?"HIGH":"LOW"), (confdone_ok?"LOW":"HIGH") );
program_done = 0;
configuration_count = 0; /* No reconfiguration */
}
}
/* Add another 'x' clock cycles while the device is in user mode.
This is not necessary and optional. Only used for debugging purposes */
if ( clock_x_cycle > 0 )
{
fprintf( stdout, "Info: Clock another %d cycles in while device is in user mode...\n", clock_x_cycle );
for ( i = 0; i < CLOCK_X_CYCLE; i++ )
{
Dump2Port( SIG_DCLK, 0, 0 );
Dump2Port( SIG_DCLK, 1, 0 );
}
}
if ( !program_done )
{
fprintf( stderr, "\nError: Configuration not successful! Error encountered...\n" );
return;
}
Dump2Port( SIG_DCLK, 1, 0 );
Dump2Port( SIG_DATA0, 1, 0 );
fprintf( stdout, "\nInfo: Configuration successful!\n" );
}
/********************************************************************************/
/* Name: CheckSignal */
/* */
/* Parameters: int signal */
/* - name of the signal (SIG_*). */
/* */
/* Return Value: Integer, the value of the signal. '0' is returned if the */
/* value of the signal is LOW, if not, the signal is HIGH. */
/* */
/* Descriptions: Return the value of the signal. */
/* */
/********************************************************************************/
static int inline CheckSignal( int signal )
{
return (fast_io_map[signal].xorval ^ (_readl(fast_io_map[signal].port_in) & fast_io_map[signal].mask)) ? 1: 0;
}
/********************************************************************************/
/* Name: Dump2Port */
/* */
/* Parameters: int signal, int data, int clk */
/* - name of the signal (SIG_*). */
/* - value to be dumped to the signal. */
/* - assert a LOW to HIGH transition to SIG_DCLK togther with */
/* [signal]. */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Dump [data] to [signal]. If [clk] is '1', a clock pulse is */
/* generated after the [data] is dumped to [signal]. */
/* */
/********************************************************************************/
static inline void Dump2Port( int signal, int data, int clk )
{
// fprintf(stderr,"d2p: %d %d %d %d\n", signal, data, clk);
if(clk)
_writel(fast_io_map[SIG_DCLK].port_0, fast_io_map[SIG_DCLK].mask)
if(!data)
_writel(fast_io_map[signal].port_0, fast_io_map[signal].mask)
else
_writel(fast_io_map[signal].port_1, fast_io_map[signal].mask)
if(clk)
_writel(fast_io_map[SIG_DCLK].port_1, fast_io_map[SIG_DCLK].mask)
}
static inline void ProgramByte( int one_byte )
{
int bit = 0;
int i = 0;
/* write from LSb to MSb */
for ( i = 0; i < 8; i++ )
{
bit = one_byte >> i;
bit = bit & 0x1;
/* Dump to DATA0 and insert a positive edge pulse at the same time */
Dump2Port( SIG_DATA0, bit, 1 );
}
}
/********************************************************************************/
/* Name: PrintError */
/* */
/* Parameters: int configuration_count */
/* - # auto-reconfiguration left */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Print error message to standard error. */
/* */
/********************************************************************************/
void PrintError( int configuration_count )
{
if ( configuration_count == 0 )
fprintf( stderr, "Error: Error in configuration #%d... \nError: Maximum number of reconfiguration reached. Exiting...\n", (RECONF_COUNT_MAX-configuration_count) );
else
{
fprintf( stderr, "Error: Error in configuration #%d... Restart configuration. Ready? <Press any key to continue>\n", (RECONF_COUNT_MAX-configuration_count) );
}
}
CC=$(CROSS_COMPILE)gcc
OBJS = cpu_io.o mb_io.o mblaster.o main.o
CFLAGS = -I. -O3
OUTPUT = fpgaboot
all: $(OBJS)
${CC} -s -o $(OUTPUT) $(OBJS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
install: all
scp $(OUTPUT) root@192.168.1.2:/root
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
/*
* arch/arm/mach-at91/include/mach/at91_pio.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* Parallel I/O Controller (PIO) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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 AT91_PIO_H
#define AT91_PIO_H
#define PIO_PER 0x00 /* Enable Register */
#define PIO_PDR 0x04 /* Disable Register */
#define PIO_PSR 0x08 /* Status Register */
#define PIO_OER 0x10 /* Output Enable Register */
#define PIO_ODR 0x14 /* Output Disable Register */
#define PIO_OSR 0x18 /* Output Status Register */
#define PIO_IFER 0x20 /* Glitch Input Filter Enable */
#define PIO_IFDR 0x24 /* Glitch Input Filter Disable */
#define PIO_IFSR 0x28 /* Glitch Input Filter Status */
#define PIO_SODR 0x30 /* Set Output Data Register */
#define PIO_CODR 0x34 /* Clear Output Data Register */
#define PIO_ODSR 0x38 /* Output Data Status Register */
#define PIO_PDSR 0x3c /* Pin Data Status Register */
#define PIO_IER 0x40 /* Interrupt Enable Register */
#define PIO_IDR 0x44 /* Interrupt Disable Register */
#define PIO_IMR 0x48 /* Interrupt Mask Register */
#define PIO_ISR 0x4c /* Interrupt Status Register */
#define PIO_MDER 0x50 /* Multi-driver Enable Register */
#define PIO_MDDR 0x54 /* Multi-driver Disable Register */
#define PIO_MDSR 0x58 /* Multi-driver Status Register */
#define PIO_PUDR 0x60 /* Pull-up Disable Register */
#define PIO_PUER 0x64 /* Pull-up Enable Register */
#define PIO_PUSR 0x68 /* Pull-up Status Register */
#define PIO_ASR 0x70 /* Peripheral A Select Register */
#define PIO_BSR 0x74 /* Peripheral B Select Register */
#define PIO_ABSR 0x78 /* AB Status Register */
#define PIO_OWER 0xa0 /* Output Write Enable Register */
#define PIO_OWDR 0xa4 /* Output Write Disable Register */
#define PIO_OWSR 0xa8 /* Output Write Status Register */
#endif
/*
* arch/arm/mach-at91/include/mach/at91_pmc.h
*
* Copyright (C) 2005 Ivan Kokshaysky
* Copyright (C) SAN People
*
* Power Management Controller (PMC) - System peripherals registers.
* Based on AT91RM9200 datasheet revision E.
*
* 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 AT91_PMC_H
#define AT91_PMC_H
#define AT91_PMC_SCER (AT91_PMC + 0x00) /* System Clock Enable Register */
#define AT91_PMC_SCDR (AT91_PMC + 0x04) /* System Clock Disable Register */
#define AT91_PMC_SCSR (AT91_PMC + 0x08) /* System Clock Status Register */
#define AT91_PMC_PCK (1 << 0) /* Processor Clock */
#define AT91RM9200_PMC_UDP (1 << 1) /* USB Devcice Port Clock [AT91RM9200 only] */
#define AT91RM9200_PMC_MCKUDP (1 << 2) /* USB Device Port Master Clock Automatic Disable on Suspend [AT91RM9200 only] */
#define AT91CAP9_PMC_DDR (1 << 2) /* DDR Clock Enable [some SAM9 only] */
#define AT91RM9200_PMC_UHP (1 << 4) /* USB Host Port Clock [AT91RM9200 only] */
#define AT91SAM926x_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91SAM926x only] */
#define AT91CAP9_PMC_UHP (1 << 6) /* USB Host Port Clock [AT91CAP9 only] */
#define AT91SAM926x_PMC_UDP (1 << 7) /* USB Devcice Port Clock [AT91SAM926x only] */
#define AT91_PMC_PCK0 (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1 (1 << 9) /* Programmable Clock 1 */
#define AT91_PMC_PCK2 (1 << 10) /* Programmable Clock 2 */
#define AT91_PMC_PCK3 (1 << 11) /* Programmable Clock 3 */
#define AT91_PMC_HCK0 (1 << 16) /* AHB Clock (USB host) [AT91SAM9261 only] */
#define AT91_PMC_HCK1 (1 << 17) /* AHB Clock (LCD) [AT91SAM9261 only] */
#define AT91_PMC_PCER (AT91_PMC + 0x10) /* Peripheral Clock Enable Register */
#define AT91_PMC_PCDR (AT91_PMC + 0x14) /* Peripheral Clock Disable Register */
#define AT91_PMC_PCSR (AT91_PMC + 0x18) /* Peripheral Clock Status Register */
#define AT91_CKGR_UCKR (AT91_PMC + 0x1C) /* UTMI Clock Register [some SAM9, CAP9] */
#define AT91_PMC_UPLLEN (1 << 16) /* UTMI PLL Enable */
#define AT91_PMC_UPLLCOUNT (0xf << 20) /* UTMI PLL Start-up Time */
#define AT91_PMC_BIASEN (1 << 24) /* UTMI BIAS Enable */
#define AT91_PMC_BIASCOUNT (0xf << 28) /* UTMI BIAS Start-up Time */
#define AT91_CKGR_MOR (AT91_PMC + 0x20) /* Main Oscillator Register [not on SAM9RL] */
#define AT91_PMC_MOSCEN (1 << 0) /* Main Oscillator Enable */
#define AT91_PMC_OSCBYPASS (1 << 1) /* Oscillator Bypass [SAM9x, CAP9] */
#define AT91_PMC_OSCOUNT (0xff << 8) /* Main Oscillator Start-up Time */
#define AT91_CKGR_MCFR (AT91_PMC + 0x24) /* Main Clock Frequency Register */
#define AT91_PMC_MAINF (0xffff << 0) /* Main Clock Frequency */
#define AT91_PMC_MAINRDY (1 << 16) /* Main Clock Ready */
#define AT91_CKGR_PLLAR (AT91_PMC + 0x28) /* PLL A Register */
#define AT91_CKGR_PLLBR (AT91_PMC + 0x2c) /* PLL B Register */
#define AT91_PMC_DIV (0xff << 0) /* Divider */
#define AT91_PMC_PLLCOUNT (0x3f << 8) /* PLL Counter */
#define AT91_PMC_OUT (3 << 14) /* PLL Clock Frequency Range */
#define AT91_PMC_MUL (0x7ff << 16) /* PLL Multiplier */
#define AT91_PMC_USBDIV (3 << 28) /* USB Divisor (PLLB only) */
#define AT91_PMC_USBDIV_1 (0 << 28)
#define AT91_PMC_USBDIV_2 (1 << 28)
#define AT91_PMC_USBDIV_4 (2 << 28)
#define AT91_PMC_USB96M (1 << 28) /* Divider by 2 Enable (PLLB only) */
#define AT91_PMC_MCKR (AT91_PMC + 0x30) /* Master Clock Register */
#define AT91_PMC_CSS (3 << 0) /* Master Clock Selection */
#define AT91_PMC_CSS_SLOW (0 << 0)
#define AT91_PMC_CSS_MAIN (1 << 0)
#define AT91_PMC_CSS_PLLA (2 << 0)
#define AT91_PMC_CSS_PLLB (3 << 0)
#define AT91_PMC_CSS_UPLL (3 << 0) /* [some SAM9 only] */
#define AT91_PMC_PRES (7 << 2) /* Master Clock Prescaler */
#define AT91_PMC_PRES_1 (0 << 2)
#define AT91_PMC_PRES_2 (1 << 2)
#define AT91_PMC_PRES_4 (2 << 2)
#define AT91_PMC_PRES_8 (3 << 2)
#define AT91_PMC_PRES_16 (4 << 2)
#define AT91_PMC_PRES_32 (5 << 2)
#define AT91_PMC_PRES_64 (6 << 2)
#define AT91_PMC_MDIV (3 << 8) /* Master Clock Division */
#define AT91RM9200_PMC_MDIV_1 (0 << 8) /* [AT91RM9200 only] */
#define AT91RM9200_PMC_MDIV_2 (1 << 8)
#define AT91RM9200_PMC_MDIV_3 (2 << 8)
#define AT91RM9200_PMC_MDIV_4 (3 << 8)
#define AT91SAM9_PMC_MDIV_1 (0 << 8) /* [SAM9,CAP9 only] */
#define AT91SAM9_PMC_MDIV_2 (1 << 8)
#define AT91SAM9_PMC_MDIV_4 (2 << 8)
#define AT91SAM9_PMC_MDIV_6 (3 << 8) /* [some SAM9 only] */
#define AT91SAM9_PMC_MDIV_3 (3 << 8) /* [some SAM9 only] */
#define AT91_PMC_PDIV (1 << 12) /* Processor Clock Division [some SAM9 only] */
#define AT91_PMC_PDIV_1 (0 << 12)
#define AT91_PMC_PDIV_2 (1 << 12)
#define AT91_PMC_PLLADIV2 (1 << 12) /* PLLA divisor by 2 [some SAM9 only] */
#define AT91_PMC_PLLADIV2_OFF (0 << 12)
#define AT91_PMC_PLLADIV2_ON (1 << 12)
#define AT91_PMC_USB (AT91_PMC + 0x38) /* USB Clock Register [some SAM9 only] */
#define AT91_PMC_USBS (0x1 << 0) /* USB OHCI Input clock selection */
#define AT91_PMC_USBS_PLLA (0 << 0)
#define AT91_PMC_USBS_UPLL (1 << 0)
#define AT91_PMC_OHCIUSBDIV (0xF << 8) /* Divider for USB OHCI Clock */
#define AT91_PMC_PCKR(n) (AT91_PMC + 0x40 + ((n) * 4)) /* Programmable Clock 0-N Registers */
#define AT91_PMC_CSSMCK (0x1 << 8) /* CSS or Master Clock Selection */
#define AT91_PMC_CSSMCK_CSS (0 << 8)
#define AT91_PMC_CSSMCK_MCK (1 << 8)
#define AT91_PMC_IER (AT91_PMC + 0x60) /* Interrupt Enable Register */
#define AT91_PMC_IDR (AT91_PMC + 0x64) /* Interrupt Disable Register */
#define AT91_PMC_SR (AT91_PMC + 0x68) /* Status Register */
#define AT91_PMC_MOSCS (1 << 0) /* MOSCS Flag */
#define AT91_PMC_LOCKA (1 << 1) /* PLLA Lock */
#define AT91_PMC_LOCKB (1 << 2) /* PLLB Lock */
#define AT91_PMC_MCKRDY (1 << 3) /* Master Clock */
#define AT91_PMC_LOCKU (1 << 6) /* UPLL Lock [some SAM9, AT91CAP9 only] */
#define AT91_PMC_OSCSEL (1 << 7) /* Slow Clock Oscillator [AT91CAP9 revC only] */
#define AT91_PMC_PCK0RDY (1 << 8) /* Programmable Clock 0 */
#define AT91_PMC_PCK1RDY (1 << 9) /* Programmable Clock 1 */
#define AT91_PMC_PCK2RDY (1 << 10) /* Programmable Clock 2 */
#define AT91_PMC_PCK3RDY (1 << 11) /* Programmable Clock 3 */
#define AT91_PMC_IMR (AT91_PMC + 0x6c) /* Interrupt Mask Register */
#define AT91_PMC_PROT (AT91_PMC + 0xe4) /* Protect Register [AT91CAP9 revC only] */
#define AT91_PMC_PROTKEY 0x504d4301 /* Activation Code */
#define AT91_PMC_VER (AT91_PMC + 0xfc) /* PMC Module Version [AT91CAP9 only] */
#endif
/*
* arch/arm/mach-at91/include/mach/at91sam9263.h
*
* (C) 2007 Atmel Corporation.
*
* Common definitions.
* Based on AT91SAM9263 datasheet revision B (Preliminary).
*
* 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 AT91SAM9263_H
#define AT91SAM9263_H
/*
* Peripheral identifiers/interrupts.
*/
#define AT91_ID_FIQ 0 /* Advanced Interrupt Controller (FIQ) */
#define AT91_ID_SYS 1 /* System Peripherals */
#define AT91SAM9263_ID_PIOA 2 /* Parallel IO Controller A */
#define AT91SAM9263_ID_PIOB 3 /* Parallel IO Controller B */
#define AT91SAM9263_ID_PIOCDE 4 /* Parallel IO Controller C, D and E */
#define AT91SAM9263_ID_US0 7 /* USART 0 */
#define AT91SAM9263_ID_US1 8 /* USART 1 */
#define AT91SAM9263_ID_US2 9 /* USART 2 */
#define AT91SAM9263_ID_MCI0 10 /* Multimedia Card Interface 0 */
#define AT91SAM9263_ID_MCI1 11 /* Multimedia Card Interface 1 */
#define AT91SAM9263_ID_CAN 12 /* CAN */
#define AT91SAM9263_ID_TWI 13 /* Two-Wire Interface */
#define AT91SAM9263_ID_SPI0 14 /* Serial Peripheral Interface 0 */
#define AT91SAM9263_ID_SPI1 15 /* Serial Peripheral Interface 1 */
#define AT91SAM9263_ID_SSC0 16 /* Serial Synchronous Controller 0 */
#define AT91SAM9263_ID_SSC1 17 /* Serial Synchronous Controller 1 */
#define AT91SAM9263_ID_AC97C 18 /* AC97 Controller */
#define AT91SAM9263_ID_TCB 19 /* Timer Counter 0, 1 and 2 */
#define AT91SAM9263_ID_PWMC 20 /* Pulse Width Modulation Controller */
#define AT91SAM9263_ID_EMAC 21 /* Ethernet */
#define AT91SAM9263_ID_2DGE 23 /* 2D Graphic Engine */
#define AT91SAM9263_ID_UDP 24 /* USB Device Port */
#define AT91SAM9263_ID_ISI 25 /* Image Sensor Interface */
#define AT91SAM9263_ID_LCDC 26 /* LCD Controller */
#define AT91SAM9263_ID_DMA 27 /* DMA Controller */
#define AT91SAM9263_ID_UHP 29 /* USB Host port */
#define AT91SAM9263_ID_IRQ0 30 /* Advanced Interrupt Controller (IRQ0) */
#define AT91SAM9263_ID_IRQ1 31 /* Advanced Interrupt Controller (IRQ1) */
/*
* User Peripheral physical base addresses.
*/
#define AT91SAM9263_BASE_UDP 0xfff78000
#define AT91SAM9263_BASE_TCB0 0xfff7c000
#define AT91SAM9263_BASE_TC0 0xfff7c000
#define AT91SAM9263_BASE_TC1 0xfff7c040
#define AT91SAM9263_BASE_TC2 0xfff7c080
#define AT91SAM9263_BASE_MCI0 0xfff80000
#define AT91SAM9263_BASE_MCI1 0xfff84000
#define AT91SAM9263_BASE_TWI 0xfff88000
#define AT91SAM9263_BASE_US0 0xfff8c000
#define AT91SAM9263_BASE_US1 0xfff90000
#define AT91SAM9263_BASE_US2 0xfff94000
#define AT91SAM9263_BASE_SSC0 0xfff98000
#define AT91SAM9263_BASE_SSC1 0xfff9c000
#define AT91SAM9263_BASE_AC97C 0xfffa0000
#define AT91SAM9263_BASE_SPI0 0xfffa4000
#define AT91SAM9263_BASE_SPI1 0xfffa8000
#define AT91SAM9263_BASE_CAN 0xfffac000
#define AT91SAM9263_BASE_PWMC 0xfffb8000
#define AT91SAM9263_BASE_EMAC 0xfffbc000
#define AT91SAM9263_BASE_ISI 0xfffc4000
#define AT91SAM9263_BASE_2DGE 0xfffc8000
#define AT91_BASE_SYS 0xffffe000
/*
* System Peripherals (offset from AT91_BASE_SYS)
*/
#define AT91_ECC0 (0xffffe000 - AT91_BASE_SYS)
#define AT91_SDRAMC0 (0xffffe200 - AT91_BASE_SYS)
#define AT91_SMC0 (0xffffe400 - AT91_BASE_SYS)
#define AT91_ECC1 (0xffffe600 - AT91_BASE_SYS)
#define AT91_SDRAMC1 (0xffffe800 - AT91_BASE_SYS)
#define AT91_SMC1 (0xffffea00 - AT91_BASE_SYS)
#define AT91_MATRIX (0xffffec00 - AT91_BASE_SYS)
#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS)
#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS)
#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS)
#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS)
#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS)
#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
#define AT91_RTT0 (0xfffffd20 - AT91_BASE_SYS)
#define AT91_PIT (0xfffffd30 - AT91_BASE_SYS)
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91_USART0 AT91SAM9263_BASE_US0
#define AT91_USART1 AT91SAM9263_BASE_US1
#define AT91_USART2 AT91SAM9263_BASE_US2
#define AT91_SMC AT91_SMC0
/*
* Internal Memory.
*/
#define AT91SAM9263_SRAM0_BASE 0x00300000 /* Internal SRAM 0 base address */
#define AT91SAM9263_SRAM0_SIZE (80 * SZ_1K) /* Internal SRAM 0 size (80Kb) */
#define AT91SAM9263_ROM_BASE 0x00400000 /* Internal ROM base address */
#define AT91SAM9263_ROM_SIZE SZ_128K /* Internal ROM size (128Kb) */
#define AT91SAM9263_SRAM1_BASE 0x00500000 /* Internal SRAM 1 base address */
#define AT91SAM9263_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */
#define AT91SAM9263_LCDC_BASE 0x00700000 /* LCD Controller */
#define AT91SAM9263_DMAC_BASE 0x00800000 /* DMA Controller */
#define AT91SAM9263_UHP_BASE 0x00a00000 /* USB Host controller */
#endif
#!/bin/sh
. ../build.settings
make CROSS_COMPILE=$CC_PATH/$CC_PREFIX $1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <fcntl.h>
#include "cpu_io.h"
static volatile uint8_t *sys_base;
static volatile uint8_t *pio_base[NUM_PIO_BANKS];
int io_init()
{
int fd = open("/dev/mem", O_RDWR);
if(!fd) return -1;
sys_base = mmap(NULL, 0x2000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, AT91_BASE_SYS);
if(sys_base == NULL)
{
perror("mmap()");
close(fd);
return -1;
}
fprintf(stderr,"AT91_SYS mmapped to: 0x%08x\n", sys_base);
pio_base[0] = sys_base + AT91_PIOA;
pio_base[1] = sys_base + AT91_PIOB;
pio_base[2] = sys_base + AT91_PIOC;
pio_base[3] = sys_base + AT91_PIOD;
pio_base[4] = sys_base + AT91_PIOE;
return 0;
}
void pio_set_state(int port, int pin, int state)
{
if(state)
_writel(pio_base[port] + PIO_SODR, (1<<pin))
else
_writel(pio_base[port] + PIO_CODR, (1<<pin))
}
void pio_set_mode(int port, int pin, int mode, int dir)
{
_writel(pio_base[port] + PIO_IDR, (1<<pin)); // disable irq
if(mode & PIN_MODE_PULLUP)
_writel(pio_base[port] + PIO_PUER, (1<<pin)) // enable pullup
else
_writel(pio_base[port] + PIO_PUDR, (1<<pin)) // disable pullup
switch(mode & 0x3)
{
case PIN_MODE_GPIO:
_writel(pio_base[port] + PIO_PER, (1<<pin)); // enable gpio mode
break;
case PIN_MODE_PERIPH_A:
_writel(pio_base[port] + PIO_PDR, (1<<pin)); // disable gpio mode
_writel(pio_base[port] + PIO_ASR, (1<<pin)); // select peripheral A
break;
case PIN_MODE_PERIPH_B:
_writel(pio_base[port] + PIO_PDR, (1<<pin)); // disable gpio mode
_writel(pio_base[port] + PIO_BSR, (1<<pin)); // select peripheral B
break;
}
if(dir)
_writel(pio_base[port] + PIO_OER, (1<<pin)) // select output
else
_writel(pio_base[port] + PIO_ODR, (1<<pin)); // select input
}
static const struct {
int port;
int pin;
int mode;
} pck_port_mapping[] =
{
{PIOA, 13, PIN_MODE_PERIPH_B},
{PIOB, 10, PIN_MODE_PERIPH_B},
{PIOA, 6, PIN_MODE_PERIPH_B},
{PIOE, 11, PIN_MODE_PERIPH_B}
};
int pck_enable(int pck_num, int prescaler, int source)
{
if(pck_num > 3) return -1;
pio_set_mode(pck_port_mapping[pck_num].port, pck_port_mapping[pck_num].pin, pck_port_mapping[pck_num].mode, 1);
_writel(sys_base + AT91_PMC_PCKR(pck_num), source | prescaler);
// enable the PCK output
_writel(sys_base + AT91_PMC_SCER, (1<< (8+pck_num)));
return 0;
}
int pio_get_state(int port, int pin)
{
return (_readl(pio_base[port] + PIO_PDSR) & (1<<pin)) ? 1: 0;
}
volatile uint8_t *io_get_sys_base()
{
return sys_base;
}
volatile uint8_t *pio_get_port_addr(int port)
{
return pio_base[port];
}
#ifndef __CPU_IO_H
#define __CPU_IO_H
#include <sys/types.h>
#include <inttypes.h>
#include <at91/at91sam9263.h>
#include <at91/at91_pio.h>
#include <at91/at91_pmc.h>
#define NUM_PIO_BANKS 5
#define PIOA 0
#define PIOB 1
#define PIOC 2
#define PIOD 3
#define PIOE 4
#define PIN_MODE_GPIO 0
#define PIN_MODE_PERIPH_A 1
#define PIN_MODE_PERIPH_B 2
#define PIN_MODE_PULLUP 0x80
#define _writel(reg, val){ *(volatile uint32_t *)(reg) = (val); }
#define _readl(reg) (*(volatile uint32_t *)(reg))
int io_init();
void pio_set_state(int port, int pin, int state);
void pio_set_mode(int port, int pin, int mode, int dir);
int pck_enable(int pck_num, int prescaler, int source);
int pio_get_state(int port, int pin);
volatile uint8_t *io_get_sys_base();
volatile uint8_t *pio_get_port_addr(int port);
#endif
#include <stdio.h>
#include <unistd.h>
#include "cpu_io.h"
#define N_LEDS 8
struct {
int port;
int pin;
} leds[] = {
{PIOC, 5},
{PIOC, 12},
{PIOC, 7},
{PIOC, 19},
{PIOC, 9},
{PIOC, 17},
{PIOC, 14},
{PIOC, 6},
{0, 0}
};
void blink_leds()
{
int i;
for(i=0;i<N_LEDS;i++)
pio_set_mode(leds[i].port, leds[i].pin, PIN_MODE_GPIO, 1);
i=0;
for(;;)
{
int prevled=((i-1)<0)?(N_LEDS-1):i-1;
pio_set_state(leds[prevled].port, leds[prevled].pin, 0);
pio_set_state(leds[i].port, leds[i].pin, 1);
i++; if(i>=N_LEDS) i = 0;
usleep(100000);
}
}
extern int mblaster_boot_fpga(const char *filename);
main(int argc, char *argv[])
{
io_init();
pck_enable(0, AT91_PMC_CSS_PLLA, AT91_PMC_PRES_2);
if(argc<2)
{
fprintf(stderr,"Filename missing!\n");
return -1;
}
mblaster_boot_fpga(argv[1]);
}
/****************************************************************************/
/* */
/* Module: mb_io.c (MicroBlaster) */
/* */
/* Copyright (C) Altera Corporation 2004 */
/* */
/* Descriptions: Defines all IO control functions. operating system */
/* is defined here. Functions are operating system */
/* dependant. */
/* */
/* Revisions: 1.0 12/10/01 Sang Beng Ng */
/* Supports Altera ByteBlaster hardware download cable */
/* on Windows NT. */
/* 1.1 05/28/04 Chuin Tein Ong */
/* Supports both Altera ByteBlaster II and ByteBlaster MV */
/* download cables on Windows NT. */
/* */
/****************************************************************************/
#include "mb_io.h"
#include <stdio.h>
int fopen_rbf( char argv[], char* mode)
{
FILE* file_id;
file_id = fopen( argv, mode );
return (int) file_id;
}
int fclose_rbf( int file_id)
{
fclose( (FILE*) file_id);
return 0;
}
int fseek_rbf( int finputid, int start, int end )
{
int seek_position;
seek_position = fseek( (FILE*) finputid, start, end );
return seek_position;
}
int ftell_rbf( int finputid )
{
int file_size;
file_size = ftell( (FILE*) finputid );
return file_size;
}
int fgetc_rbf( int finputid )
{
int one_byte;
one_byte = fgetc( (FILE*) finputid );
return one_byte;
}
void delay ( int factor)
{
int i;
for (i=0;i<factor;i++) asm volatile("nop");
}
\ No newline at end of file
/****************************************************************************/
/* */
/* Module: mb_io.h (MicroBlaster) */
/* */
/* Copyright (C) Altera Corporation 2004 */
/* */
/* Descriptions: Defines all IO control functions. operating system */
/* is defined here. Functions are operating system */
/* dependant. */
/* */
/* Revisions: 1.0 12/10/01 Sang Beng Ng */
/* Supports Altera ByteBlaster hardware download cable */
/* on Windows NT. */
/* 1.1 05/28/04 Chuin Tein Ong */
/* Supports both Altera ByteBlaster II and ByteBlaster MV */
/* download cables on Windows NT. */
/* */
/****************************************************************************/
#ifndef INC_MB_IO_H
#define INC_MB_IO_H
#define EMBEDDED 2
/*///////////////////////*/
/* Functions Prototyping */
/*///////////////////////*/
int ReadByteBlaster ( int port );
void WriteByteBlaster ( int port, int data, int test );
#endif /* INC_MB_IO_H */
\ No newline at end of file
#include "mb_io.h"
#include <stdio.h>
#include "cpu_io.h"
#define SIG_DCLK 0 /* Passive Serial configuration signals */
#define SIG_NCONFIG 1
#define SIG_DATA0 2
#define SIG_NSTATUS 3
#define SIG_CONFDONE 4
#define S_CUR 1 /* SEEK_CUR */
#define S_END 2 /* SEEK_END */
#define S_SET 0 /* SEEK_SET */
/********************/
/* User definations */
/*//////////////////*/
#define INIT_CYCLE 50 /* extra DCLK cycles while initialization is in progress */
#define RECONF_COUNT_MAX 5 /* #auto-reconfiguration when error found */
#define CHECK_EVERY_X_BYTE 10240 /* check NSTATUS pin for error for every X bytes */
/* DO NOT put '0' */
#define CLOCK_X_CYCLE 0 /* clock another 'x' cycles during user mode (not necessary,
for debug purpose only) */
/*///////////////////////*/
/* Functions Prototyping */
/*///////////////////////*/
static inline int CheckSignal ( int signal );
static inline void Dump2Port ( int signal, int data, int clk );
void PrintError ( int configuration_count );
void ProcessFileInput ( int finputid );
static inline void ProgramByte ( int one_byte );
void SetPortMode ( int mode );
/* Version Number */
const char VERSION[4] = "1.1";
/********************************************************************************/
/* Name: Main */
/* */
/* Parameters: int argc, char* argv[] */
/* - number of argument. */
/* - argument character pointer. */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Open programming file and initialize driver if required */
/* (WINDOWS NT). */
/* */
/********************************************************************************/
static const struct {
int port;
int pin;
int mode;
int dir;
int invert;
} io_mapping [] = {
{ PIOB, 1, PIN_MODE_GPIO, 1, 0}, // SIG_DCLK
{ PIOB, 22, PIN_MODE_GPIO, 1, 0}, // SIG_NCONFIG
{ PIOB, 2, PIN_MODE_GPIO, 1, 0}, // SIG_DATA0
{ PIOB, 31, PIN_MODE_GPIO, 0, 0}, // SIG_NSTATUS
{ PIOB, 18, PIN_MODE_GPIO, 0, 1} // SIG_CONFDONE
};
struct {
volatile uint8_t *port_in;
volatile uint8_t *port_1;
volatile uint8_t *port_0;
uint32_t mask;
uint32_t xorval;
} fast_io_map[5];
void port_init()
{
int i;
for(i=0; i<5; i++)
{
pio_set_state(io_mapping[i].port, io_mapping[i].pin, 1);
pio_set_mode(io_mapping[i].port, io_mapping[i].pin, io_mapping[i].mode, io_mapping[i].dir);
fast_io_map[i].port_in = pio_get_port_addr(io_mapping[i].port) + PIO_PDSR;
fast_io_map[i].port_0 = pio_get_port_addr(io_mapping[i].port) + PIO_CODR;
fast_io_map[i].port_1 = pio_get_port_addr(io_mapping[i].port) + PIO_SODR;
fast_io_map[i].mask = (1 << io_mapping[i].pin);
fast_io_map[i].xorval = io_mapping[i].invert ? (1 << io_mapping[i].pin) : 0;
}
}
int mblaster_boot_fpga(const char *filename)
{
int file_id;
port_init();
file_id = fopen_rbf( filename, "rb" );
if ( file_id )
fprintf( stdout, "Info: Programming file: \"%s\" opened...\n", filename );
else
{
fprintf( stderr, "Error: Could not open programming file: \"%s\"\n", filename );
return;
}
ProcessFileInput( file_id );
if ( file_id )
fclose_rbf(file_id);
return 0;
}
/********************************************************************************/
/* Name: ProcessFileInput */
/* */
/* Parameters: FILE* finputid */
/* - programming file pointer. */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Get programming file size, parse through every single byte */
/* and dump to parallel port. */
/* */
/* Configuration Hardware is verified before configuration */
/* starts. */
/* */
/* For every [CHECK_EVERY_X_BYTE] bytes, NSTATUS pin is */
/* checked for error. When the file size reached, CONF_DONE */
/* pin is checked for configuration status. Then, another */
/* [INIT_CYCLE] clock cycles are dumped while initialization */
/* is in progress. */
/* */
/* Configuration process is restarted whenever error found. */
/* The maximum number of auto-reconfiguration is */
/* [RECONF_COUNT_MAX]. */
/* */
/********************************************************************************/
void ProcessFileInput( int finputid )
{
int program_done = 0; /* programming process (configuration and initialization) done = 1 */
int seek_position = 0; /* file pointer position */
long int file_size = 0; /* programming file size */
int configuration_count = RECONF_COUNT_MAX; /* # reprogramming after error */
int one_byte = 0; /* the byte to program */
long int i = 0; /* standard counter variable */
int confdone_ok = 1; /* CONF_DONE pin. '1' - error */
int nstatus_ok = 0; /* NSTATUS pin. '0' - error */
int clock_x_cycle = CLOCK_X_CYCLE; /* Clock another 'x' cycles during user mode ( not necessary, for debug purpose only) */
int BBMV=0;
int BBII=0;
/* Get file size */
seek_position = fseek_rbf( finputid, 0, S_END );
if ( seek_position )
{
fprintf( stderr, "Error: End of file could not be located!" );
return;
}
file_size = ftell_rbf( finputid );
fprintf( stdout, "Info: Programming file size: %ld\n", file_size );
/* Start configuration */
while ( !program_done && (configuration_count>0) )
{
/* Reset file pointer and parallel port registers */
fseek_rbf( finputid, 0, S_SET );
fprintf( stdout, "\n***** Start configuration process *****\nPlease wait...\n" );
/* Drive a transition of 0 to 1 to NCONFIG to indicate start of configuration */
Dump2Port( SIG_NCONFIG, 0, 0 );
Dump2Port( SIG_NCONFIG, 1, 0 );
/* Loop through every single byte */
for ( i = 0; i < file_size; i++ )
{
/*one_byte = fgetc( (FILE*) finputid );*/
one_byte = fgetc_rbf( finputid );
/* Progaram a byte */
ProgramByte( one_byte );
/* Check for error through NSTATUS for every 10KB programmed and the last byte */
if ( !(i % CHECK_EVERY_X_BYTE) || (i == file_size - 1) )
{
nstatus_ok = CheckSignal( SIG_NSTATUS );
if ( !nstatus_ok )
{
PrintError( configuration_count-1 );
program_done = 0;
break;
}
else
program_done = 1;
}
}
configuration_count--;
if ( !program_done )
continue;
/* Configuration end */
/* Check CONF_DONE that indicates end of configuration */
confdone_ok = CheckSignal( SIG_CONFDONE );
if ( confdone_ok )
{
fprintf( stderr, "Error: Configuration done but contains error... CONF_DONE is %s\n", (confdone_ok? "LOW":"HIGH") );
program_done = 0;
PrintError( configuration_count );
if ( configuration_count == 0 )
break;
}
/* if contain error during configuration, restart configuration */
if ( !program_done )
continue;
/* program_done = 1; */
/* Start initialization */
/* Clock another extra DCLK cycles while initialization is in progress
through internal oscillator or driving clock cycles into CLKUSR pin */
/* These extra DCLK cycles do not initialize the device into USER MODE */
/* It is not required to drive extra DCLK cycles at the end of
configuration */
/* The purpose of driving extra DCLK cycles here is to insert some delay
while waiting for the initialization of the device to complete before
checking the CONFDONE and NSTATUS signals at the end of whole
configuration cycle */
for ( i = 0; i < INIT_CYCLE; i++ )
{
Dump2Port( SIG_DCLK, 0, 0 );
Dump2Port( SIG_DCLK, 1, 0 );
}
/* Initialization end */
nstatus_ok = CheckSignal( SIG_NSTATUS );
confdone_ok = CheckSignal( SIG_CONFDONE );
if ( !nstatus_ok || confdone_ok )
{
fprintf( stderr, "Error: Initialization finish but contains error: NSTATUS is %s and CONF_DONE is %s. Exiting...", (nstatus_ok?"HIGH":"LOW"), (confdone_ok?"LOW":"HIGH") );
program_done = 0;
configuration_count = 0; /* No reconfiguration */
}
}
/* Add another 'x' clock cycles while the device is in user mode.
This is not necessary and optional. Only used for debugging purposes */
if ( clock_x_cycle > 0 )
{
fprintf( stdout, "Info: Clock another %d cycles in while device is in user mode...\n", clock_x_cycle );
for ( i = 0; i < CLOCK_X_CYCLE; i++ )
{
Dump2Port( SIG_DCLK, 0, 0 );
Dump2Port( SIG_DCLK, 1, 0 );
}
}
if ( !program_done )
{
fprintf( stderr, "\nError: Configuration not successful! Error encountered...\n" );
return;
}
Dump2Port( SIG_DCLK, 1, 0 );
Dump2Port( SIG_DATA0, 1, 0 );
fprintf( stdout, "\nInfo: Configuration successful!\n" );
}
/********************************************************************************/
/* Name: CheckSignal */
/* */
/* Parameters: int signal */
/* - name of the signal (SIG_*). */
/* */
/* Return Value: Integer, the value of the signal. '0' is returned if the */
/* value of the signal is LOW, if not, the signal is HIGH. */
/* */
/* Descriptions: Return the value of the signal. */
/* */
/********************************************************************************/
static int inline CheckSignal( int signal )
{
return (fast_io_map[signal].xorval ^ (_readl(fast_io_map[signal].port_in) & fast_io_map[signal].mask)) ? 1: 0;
}
/********************************************************************************/
/* Name: Dump2Port */
/* */
/* Parameters: int signal, int data, int clk */
/* - name of the signal (SIG_*). */
/* - value to be dumped to the signal. */
/* - assert a LOW to HIGH transition to SIG_DCLK togther with */
/* [signal]. */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Dump [data] to [signal]. If [clk] is '1', a clock pulse is */
/* generated after the [data] is dumped to [signal]. */
/* */
/********************************************************************************/
static inline void Dump2Port( int signal, int data, int clk )
{
// fprintf(stderr,"d2p: %d %d %d %d\n", signal, data, clk);
if(clk)
_writel(fast_io_map[SIG_DCLK].port_0, fast_io_map[SIG_DCLK].mask)
if(!data)
_writel(fast_io_map[signal].port_0, fast_io_map[signal].mask)
else
_writel(fast_io_map[signal].port_1, fast_io_map[signal].mask)
if(clk)
_writel(fast_io_map[SIG_DCLK].port_1, fast_io_map[SIG_DCLK].mask)
}
static inline void ProgramByte( int one_byte )
{
int bit = 0;
int i = 0;
/* write from LSb to MSb */
for ( i = 0; i < 8; i++ )
{
bit = one_byte >> i;
bit = bit & 0x1;
/* Dump to DATA0 and insert a positive edge pulse at the same time */
Dump2Port( SIG_DATA0, bit, 1 );
}
}
/********************************************************************************/
/* Name: PrintError */
/* */
/* Parameters: int configuration_count */
/* - # auto-reconfiguration left */
/* */
/* Return Value: None. */
/* */
/* Descriptions: Print error message to standard error. */
/* */
/********************************************************************************/
void PrintError( int configuration_count )
{
if ( configuration_count == 0 )
fprintf( stderr, "Error: Error in configuration #%d... \nError: Maximum number of reconfiguration reached. Exiting...\n", (RECONF_COUNT_MAX-configuration_count) );
else
{
fprintf( stderr, "Error: Error in configuration #%d... Restart configuration. Ready? <Press any key to continue>\n", (RECONF_COUNT_MAX-configuration_count) );
}
}
CC=gcc
OBJS = gen_pll_coefs.o
LDFLAGS =
CFLAGS =
OUTPUT = gen_pll_coefs
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
static const struct ad9516_regs ad9516_regs_tcxo = {
{
{ 0x0000, 0x18},
{ 0x0001, 0x00},
{ 0x0002, 0x10},
{ 0x0003, 0xc3},
{ 0x0004, 0x00},
{ 0x0010, 0x7c},
{ 0x0011, 0x01},
{ 0x0012, 0x00},
{ 0x0013, 0x06},
{ 0x0014, 0x08},
{ 0x0015, 0x00},
{ 0x0016, 0x04},
{ 0x0017, 0x00},
{ 0x0018, 0x07},
{ 0x0019, 0x00},
{ 0x001a, 0x00},
{ 0x001b, 0x00},
{ 0x001c, 0x06},
{ 0x001d, 0x00},
{ 0x001e, 0x00},
{ 0x001f, 0x0e},
{ 0x00a0, 0x01},
{ 0x00a1, 0x00},
{ 0x00a2, 0x00},
{ 0x00a3, 0x01},
{ 0x00a4, 0x00},
{ 0x00a5, 0x00},
{ 0x00a6, 0x01},
{ 0x00a7, 0x00},
{ 0x00a8, 0x00},
{ 0x00a9, 0x01},
{ 0x00aa, 0x00},
{ 0x00ab, 0x00},
{ 0x00f0, 0x0a},
{ 0x00f1, 0x0a},
{ 0x00f2, 0x0a},
{ 0x00f3, 0x0a},
{ 0x00f4, 0x0a},
{ 0x00f5, 0x08},
{ 0x0140, 0x42},
{ 0x0141, 0x42},
{ 0x0142, 0x42},
{ 0x0143, 0x5a},
{ 0x0190, 0x00},
{ 0x0191, 0x80},
{ 0x0192, 0x00},
{ 0x0193, 0x32},
{ 0x0194, 0x00},
{ 0x0195, 0x00},
{ 0x0196, 0x32},
{ 0x0197, 0x00},
{ 0x0198, 0x00},
{ 0x0199, 0x32},
{ 0x019a, 0x00},
{ 0x019b, 0x11},
{ 0x019c, 0x20},
{ 0x019d, 0x00},
{ 0x019e, 0x32},
{ 0x019f, 0x00},
{ 0x01a0, 0x11},
{ 0x01a1, 0x20},
{ 0x01a2, 0x00},
{ 0x01a3, 0x00},
{ 0x01e0, 0x00},
{ 0x01e1, 0x02},
{ 0x0230, 0x00},
{ 0x0231, 0x00},
{ 0x0232, 0x00},
{ 0x0232, 0x00},
{0}},
69
};
\ No newline at end of file
#include <stdio.h>
#include <inttypes.h>
#define AD9516_MAX_REGS 1024
struct ad9516_regs {
struct {
uint16_t addr;
uint8_t value;
} regs[AD9516_MAX_REGS];
int nregs;
};
int ad9516_load_regset(const char *filename, struct ad9516_regs *regs)
{
FILE *f;
char str[1024], tmp[100];
int start_read = 0, n = 0;
uint32_t addr, val;
f = fopen(filename ,"rb");
if(!f)
{
return -1;
}
while(!feof(f))
{
if(fgets(str, 1024, f) == EOF) break;
// printf("%s\n",str);
if(!strncmp(str, "Addr(Hex)", 8)) start_read = 1;
if(start_read)
{
if( sscanf(str, "%04x %08s %02x\n", &addr, tmp, &val) == 3)
{
regs->regs[n].addr = addr;
regs->regs[n].value = val;
n++;
}
}
}
regs->nregs = n;
fclose(f);
return 0;
}
main(int argc, char *argv[])
{
struct ad9516_regs r;
int i;
ad9516_load_regset(argv[1], &r);
printf("static const struct ad9516_regs %s = {\n", argv[2]);
printf("{\n");
for(i=0;i<r.nregs;i++)
{
printf( " { 0x%04x, 0x%02x},\n", r.regs[i].addr, r.regs[i].value);
}
printf("\n{0}},\n %d\n};", r.nregs);
return 0;
}
AD9516/17/18 Register Map File, Rev 1.0
Addr(Hex) Value(Bin) Value(Hex)
0000 00011000 18
0001 00000000 00
0002 00010000 10
0003 11000011 C3
0004 00000000 00
0010 01111100 7C
0011 00000001 01
0012 00000000 00
0013 00000110 06
0014 00001000 08
0015 00000000 00
0016 00000100 04
0017 00000000 00
0018 00000111 07
0019 00000000 00
001A 00000000 00
001B 00000000 00
001C 00000110 06
001D 00000000 00
001E 00000000 00
001F 00001110 0E
00A0 00000001 01
00A1 00000000 00
00A2 00000000 00
00A3 00000001 01
00A4 00000000 00
00A5 00000000 00
00A6 00000001 01
00A7 00000000 00
00A8 00000000 00
00A9 00000001 01
00AA 00000000 00
00AB 00000000 00
00F0 00001010 0A
00F1 00001010 0A
00F2 00001010 0A
00F3 00001010 0A
00F4 00001010 0A
00F5 00001000 08
0140 01000010 42
0141 01000010 42
0142 01000010 42
0143 01011010 5A
0190 00000000 00
0191 10000000 80
0192 00000000 00
0193 00110010 32
0194 00000000 00
0195 00000000 00
0196 00110010 32
0197 00000000 00
0198 00000000 00
0199 00110010 32
019A 00000000 00
019B 00010001 11
019C 00100000 20
019D 00000000 00
019E 00110010 32
019F 00000000 00
01A0 00010001 11
01A1 00100000 20
01A2 00000000 00
01A3 00000000 00
01E0 00000000 00
01E1 00000010 02
0230 00000000 00
0231 00000000 00
0232 00000000 00
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = hal_client.o
LDFLAGS = -lswitchhw -L../../libswitchhw -L../../libwripc -lwripc
CFLAGS = -I. -O2 -I../../include -I../../wrsw_hal -I../../libwripc -DDEBUG
OUTPUT = hal_client
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) ../../drivers/bin/*.ko root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include <wr_ipc.h>
#include <wrsw_hal.h>
static wripc_handle_t hal_cli;
int halcli_check_running()
{
int rval;
wripc_call(hal_cli, "halexp_check_running", &rval, 0);
return rval;
}
main()
{
hal_cli = wripc_connect("wrsw_hal");
if(hal_cli < 0)
{
printf("Unable to connect to HAL\n");
return -1;
}
printf("HAL status: %s\n", halcli_check_running() ? "running" : "inactive");
}
CC=$(CROSS_COMPILE)gcc
OBJS = hello.o
LDFLAGS =
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = hello
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run:: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
t=`pwd`
cd ../../libswitchhw
./build.sh clean
./build.sh
cd $t
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
main() { printf("dupa!"); };
\ No newline at end of file
CC=$(CROSS_COMPILE)gcc
OBJS = hpll_wishbone_test.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = hpll_wishbone_test
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <hw/hpll_regs.h>
int sign_extend(uint32_t val, int nbits)
{
if(val & (1<<(nbits-1))) return (0xffffffff ^ ((1<<nbits)-1)) | val; else return val;
}
main(int argc, char *argv[])
{
if(argc < 3) return -1;
FILE *fin, *fout;
uint32_t r0;
int npoints;
int i = 0;
fin = fopen(argv[1], "rb");
fout = fopen(argv[2], "wb");
npoints = atoi(argv[3]);
while(!feof(fin) && (++i < npoints))
{
fread(&r0, 4, 1, fin);
fprintf(fout, "%d %d %d %d\n", i,
sign_extend(HPLL_RFIFO_R0_ERR_VAL_R(r0), 12),
HPLL_RFIFO_R0_DAC_VAL_R(r0),
r0 & HPLL_RFIFO_R0_FP_MODE ? 60000 : 0);
}
}
\ No newline at end of file
#include <stdio.h>
#include <inttypes.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
main()
{
trace_log_stderr();
shw_init();
// force the PHY enable/sync enable line HI
_fpga_writel(FPGA_BASE_GIGASPY_UP1 | GSPY_REG_GSTESTCTL, GSPY_GSTESTCTL_PHYIO_ENABLE | GSPY_GSTESTCTL_PHYIO_SYNCEN);
// set up the crosspoint to pass the data from PHY to SFPs
xpoint_configure();
shw_hpll_init();
for(;;)
{
printf("Locked: %d\n", shw_hpll_check_lock() ? 1: 0);
shw_hpll_update();
}
}
#!/bin/bash
IP=192.168.1.6
scp root@$IP:/tmp/hpll_meas.dat ./
./convert_meas hpll_meas.dat hpll_plotdata.dat 100000
gnuplot -e "set xlabel 'time'; set ylabel 'DAC value'; set y2label 'Phase/freq error'; set yrange [-10000:10000]; set y2range [0:65540]; plot 'hpll_plotdata.dat' using 1:2 title 'Phase/freq error' with lines axis x1y1, \
'hpll_plotdata.dat' using 1:3 title 'DAC drive' with lines axis x1y2, \
'hpll_plotdata.dat' using 1:4 title 'Freq/Phase mode' with lines axis x1y2; \
"
#, plot "hpll_plotdata.dat" using 1:3 title "integral value" with lines, plot "hpll_plotdata.dat" using 1:4 title "DAC drive" with lines'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
CC=$(CROSS_COMPILE)gcc
OBJS = minic_test.o term.o gigaspy.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include
OUTPUT = minic_test
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
${CC} -o timestamping timestamping.c $(CFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) ../../drivers/bin/*.ko root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
cd ../../libswitchhw
./build.sh
cd ../tests/minic_test
cd ../../drivers/wr_minic
./build.sh
cd ../../tests/minic_test
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
#include <hw/gigaspy_regs.h>
#include "gigaspy.h"
static inline void _gspy_writel(shw_gigaspy_context_t *gspy, uint32_t reg, uint32_t val)
{
*(volatile uint32_t *) (gspy->base + reg) = val;
}
static inline uint32_t _gspy_readl(shw_gigaspy_context_t *gspy, uint32_t reg)
{
uint32_t tmp = *(volatile uint32_t *)(gspy->base+reg);
return tmp;
}
shw_gigaspy_context_t *shw_gigaspy_init(uint32_t base_addr, int buffer_size)
{
shw_gigaspy_context_t *ctx;
ctx = shw_malloc(sizeof(shw_gigaspy_context_t));
ctx->base = (void*)_fpga_base_virt + base_addr;
ctx->buf_size = buffer_size;
return ctx;
}
void shw_gigaspy_configure(shw_gigaspy_context_t *gspy, int mode, int trig_source, int trig0, int trig1, int num_samples)
{
uint32_t gsctl = 0;
_gspy_writel(gspy, GSPY_REG_GSNSAMPLES, num_samples);
gspy->cur_nsamples = num_samples;
if(trig0 == TRIG_UNUSED && trig1 == TRIG_UNUSED)
_gspy_writel(gspy, GSPY_REG_GSTRIGCTL, 0); // no trigger (free-running mode)
else if (trig1 == TRIG_UNUSED)
_gspy_writel(gspy, GSPY_REG_GSTRIGCTL, trig0 | GSPY_GSTRIGCTL_TRIG0_EN(1));
else
_gspy_writel(gspy, GSPY_REG_GSTRIGCTL,
trig0 | GSPY_GSTRIGCTL_TRIG0_EN(1) |
(trig1<<16) | GSPY_GSTRIGCTL_TRIG1_EN(1));
gsctl = GSPY_GSCTL_CH0_ENABLE(1) | GSPY_GSCTL_CH1_ENABLE(1);
if(trig_source == GIGASPY_CH0)
gsctl |= GSPY_GSCTL_LOAD_TRIG0(1);// | GSPY_GSCTL_SLAVE0_ENABLE(1);
else
gsctl |= GSPY_GSCTL_LOAD_TRIG1(1);// | GSPY_GSCTL_SLAVE1_ENABLE(1);
gspy->cur_trig_src = trig_source;
printf("gsctl = %x\n", gsctl);
printf("trigctl = %x\n", _gspy_readl(gspy, GSPY_REG_GSTRIGCTL));
_gspy_writel(gspy, GSPY_REG_GSCTL, gsctl);
}
void shw_gigaspy_arm(shw_gigaspy_context_t *gspy)
{
uint32_t gsctl = _gspy_readl(gspy, GSPY_REG_GSCTL);
gsctl |= GSPY_GSCTL_RESET_TRIG0(1) | GSPY_GSCTL_RESET_TRIG1(1);
_gspy_writel(gspy, GSPY_REG_GSCTL, gsctl);
}
int shw_gigaspy_poll(shw_gigaspy_context_t *gspy)
{
uint32_t gsstat = _gspy_readl(gspy, GSPY_REG_GSSTAT);
// printf("GSSTAT: %x\n", gsstat);
if(gspy->cur_trig_src == GIGASPY_CH0)
return GSPY_GSSTAT_TRIG_DONE0(gsstat);
else
return GSPY_GSSTAT_TRIG_DONE1(gsstat);
}
static void read_gsbuf(shw_gigaspy_context_t *gspy, int ch, uint32_t addr, int n, uint32_t *buf)
{
uint32_t p, base = (ch == GIGASPY_CH0 ? (4*gspy->buf_size): (8*gspy->buf_size));
int i;
printf("baseaddr %x\n", base);
for(i=0;i<n;i++)
{
p = addr+i*4;
p &= ((4*gspy->buf_size)-1);
buf[i]=_gspy_readl(gspy, base+p);
}
}
static void hexprint(int start_addr, uint32_t *buf, int size)
{
int nempty = 0;
int n=0,i=0;
nempty = (start_addr % 16);
while(n<size)
{
if((i%16)==0)printf("\n%03x: ", start_addr + n);
if(nempty)
{
printf(" ");
nempty--;
} else {
int pos = (n+start_addr)&0x1fff;
printf(" %c%02x", buf[pos]&0x100?'K':' ', buf[pos]&0xff);
n++;
}
i++;
}
printf("\n");
}
static void dump_packet(int offs, int n, uint32_t *buf)
{
hexprint(offs, buf, n);
}
#define buf_get(x) buf[(offs+(x))&0x1fff]
static void dump_packet_ether(int offs, int n, uint32_t *buf)
{
int sfd_pos=-1;
int efd_pos=-1;
int i;
int fstart=0;
for(i=0;i<n;i++)
{
if((buf_get(i) == 0x1fb) && (sfd_pos<0)) sfd_pos = i;
if((buf_get(i) == 0x1fd) && (efd_pos<0)) efd_pos = i;
}
if(efd_pos < 0) {printf("dump_frame(): no EPD\n");return ; }
if(sfd_pos < 0) {printf("dump_frame(): no SFD\n");return ; }
if(sfd_pos >= efd_pos){printf("dump_frame(): SFD>EPD\n");return ; }
for(i=sfd_pos+1; i<sfd_pos+6;i++) if(buf_get(i)!=0x55) { printf("Adump_frame(): invalid preamble\n");return ; }
if((buf_get(sfd_pos+6) == 0x55) && (buf_get(sfd_pos+7) == 0xd5))fstart = sfd_pos+8;
if((buf_get(sfd_pos+6) == 0xd5)) fstart = sfd_pos+7;
if(!fstart) { printf("Bdump_frame(): invalid preamble\n"); return ;}
printf("ETHER DSTMac=%02x:%02x:%02x:%02x:%02x:%02x SRCMac=%02x:%02x:%02x:%02x:%02x:%02x Ethertype=0x%04x\n",
buf_get(sfd_pos+8), buf_get(sfd_pos+9),buf_get(sfd_pos+10),buf_get(sfd_pos+11),buf_get(sfd_pos+12),buf_get(sfd_pos+13),
buf_get(sfd_pos+14), buf_get(sfd_pos+15),buf_get(sfd_pos+16),buf_get(sfd_pos+17),buf_get(sfd_pos+18),buf_get(sfd_pos+19),
(buf_get(sfd_pos+20) << 8) + buf_get(sfd_pos+21));
}
void shw_gigaspy_dump(shw_gigaspy_context_t *gspy, int pretrigger, int num_samples, int mode, int channels)
{
uint32_t buf_ch0[GIGASPY_MAX_MEM_SIZE];
uint32_t buf_ch1[GIGASPY_MAX_MEM_SIZE];
uint32_t gstrigaddr = _gspy_readl(gspy, GSPY_REG_GSTRIGADDR);
uint32_t addr_ch0 = GSPY_GSTRIGADDR_CH0(gstrigaddr);
uint32_t addr_ch1 = GSPY_GSTRIGADDR_CH1(gstrigaddr);
read_gsbuf(gspy, GIGASPY_CH0, 0, gspy->buf_size, buf_ch0);
read_gsbuf(gspy, GIGASPY_CH1, 0, gspy->buf_size, buf_ch1);
if(channels & GIGASPY_CH0)
{
printf("---> CH0 dump: ");
if(mode == GIGASPY_DUMP_RAW)
// dump_packet(0, pretrigger + num_samples, buf_ch0 );
dump_packet((addr_ch0-gspy->cur_nsamples-pretrigger)&(gspy->buf_size-1), pretrigger+num_samples, buf_ch0 );
else
dump_packet_ether((addr_ch0-gspy->cur_nsamples-pretrigger)&0x1fff, pretrigger+num_samples, buf_ch0 );
}
if(channels & GIGASPY_CH1)
{
printf("---> CH1 dump: ");
if(mode == GIGASPY_DUMP_RAW)
dump_packet((addr_ch1-gspy->cur_nsamples-pretrigger)&0x1fff, pretrigger+num_samples, buf_ch1 );
else
dump_packet_ether((addr_ch1-gspy->cur_nsamples-pretrigger)&0x1fff, pretrigger+num_samples, buf_ch1 );
}
}
#ifndef __GIGASPY_H
#define __GIGASPY_H
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
#define GIGASPY_CH0 0x1
#define GIGASPY_CH1 0x2
#define GIGASPY_KD(k,d) (((k)?(1<<8):0) | ((d) & 0xff))
#define GIGASPY_MAX_MEM_SIZE 16384
#define GIGASPY_DUMP_RAW 0
#define GIGASPY_DUMP_ETHER 1
#define TRIG_UNUSED -1
typedef struct {
int buf_size;
volatile void *base;
int cur_trig_src;
int cur_port;
int cur_nsamples;
} shw_gigaspy_context_t;
shw_gigaspy_context_t *shw_gigaspy_init(uint32_t base_addr, int buffer_size);
void shw_gigaspy_configure(shw_gigaspy_context_t *gspy, int mode, int trig_source, int trig0, int trig1, int num_samples);
void shw_gigaspy_arm(shw_gigaspy_context_t *gspy);
int shw_gigaspy_poll(shw_gigaspy_context_t *gspy);
void shw_gigaspy_dump(shw_gigaspy_context_t *gspy, int pretrigger, int num_samples, int mode, int channels);
#endif
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <sys/time.h>
#include <signal.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
#include <hw/minic_regs.h>
#include <hw/endpoint_regs.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
//#include <net/if.h>
#include <asm/types.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/net_tstamp.h>
#include <linux/sockios.h>
#include <linux/errqueue.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <errno.h>
#define MINIC_PBUF_SIZE_LOG2 (12)
#define MINIC_PBUF_SIZE (1<<MINIC_PBUF_SIZE_LOG2)
#define MINIC_BASE_ENDPOINT (1<<(MINIC_PBUF_SIZE_LOG2+2))
static inline void _ep_writel(uint32_t reg, uint32_t value)
{
_fpga_writel(FPGA_BASE_MINIC_UP1 + MINIC_BASE_ENDPOINT + reg, value);
}
static inline uint32_t _ep_readl(uint32_t reg)
{
return _fpga_readl(FPGA_BASE_MINIC_UP1 + MINIC_BASE_ENDPOINT + reg);
}
void endpoint_init()
{
// printf("Endpoint_init, base addr = %x\n", MINIC_BASE_ENDPOINT);
_ep_writel(EP_REG_ECR, 0); // ECR = 0?
_ep_writel(EP_REG_TCR, EP_TCR_EN_FRA | EP_TCR_EN_PCS); // enable TX framer + PCS
_ep_writel(EP_REG_RCR, EP_RCR_EN_FRA | EP_RCR_EN_PCS); // enable RX framer + PCS
_ep_writel(EP_REG_RFCR, 3 << EP_RFCR_QMODE_SHIFT); // QMODE = UNQUALIFIED
_ep_writel(EP_REG_MACH, 0xaabb); // assign a dummy MAC address
_ep_writel(EP_REG_MACL, 0xccddeeff);
_ep_writel(EP_REG_TSCR, 0);
_ep_writel(EP_REG_PHIO, EP_PHIO_ENABLE | EP_PHIO_SYNCEN); // enable the PHY
shw_pio_set0(PIN_up1_sfp_tx_disable); // enable the SFP
shw_pio_set0(PIN_up0_sfp_tx_disable); // enable the SFP
fprintf(stderr,"EP: waiting for sync...\n");
// while(!(_ep_readl(EP_REG_RCR) & EP_RCR_SYNCED));
// _ep_writel(EP_REG_TCR, EP_TCR_TX_CAL); // enable TX framer + PCS
// printf("LCW: %x\n", ep_rx_lcw(0));
// printf("LCW: %x\n", ep_rx_lcw(0));
return ;
}
int shw_ad9516_set_output_delay(int output, float delay_ns, int bypass);
void dump_counters()
{
const char *cntr_names[] = {
"0x0 : TX PCS buffer underruns",
"0x4 : RX PCS invalid 8b10b codes",
"0x8 : RX PCS sync lost events",
"0xc : RX PCS buffer overruns",
"0x10: RX CRC errors",
"0x14: RX valid frames",
"0x18: RX runt frames",
"0x1c: RX giant frames",
"0x20: RX PCS errors",
"0x24: RX dropped frames"
};
int i;
for(i=0;i<10;i++) printf("%-30s: %d\n", cntr_names[i], _ep_readl(0x80 + 4*i));
}
uint64_t get_tics()
{
struct timezone tz = {0,0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
#define SO_TXTS_FRAME_TAG 38
static int poll_tx_timestamp(int sock, uint32_t *raw_ts)
{
char data[2048];
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[512];
} control;
int res;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
res = recvmsg(sock, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
if(res >= 0)
{
fprintf(stderr,"GotErrQ\n");
}
return 0;
}
int test_tx_timestamps()
{
uint64_t tstart;
struct hwtstamp_config hwconfig;
struct sockaddr_ll sll, dest_addr;
struct ifreq f;
const char *if_name = "wru1";
const uint16_t if_ethertype = 0x88f7;
int enable;
int fd;
int ts_flags;
const uint8_t broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t my_mac[] = {0x00 ,0x50, 0xfc, 0x96, 0x9b, 0x0e};
fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd < 0) { perror("socket()"); return -1; }
// strcpy(f.ifr_name, if_name);
// if(ioctl(fd, SIOCGIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
// f.ifr_flags |= IFF_PROMISC;
// if(ioctl(fd, SIOCSIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
strcpy(f.ifr_name, if_name);
ioctl(fd, SIOCGIFINDEX, &f);
sll.sll_ifindex = f.ifr_ifindex;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(if_ethertype);
sll.sll_halen = 6;
if(bind(fd, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)) < 0)
{
close(fd);
perror("bind()");
return NULL;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
hwconfig.tx_type = HWTSTAMP_TX_ON;
hwconfig.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
memset(&f, 0, sizeof(struct ifreq));
f.ifr_data = &hwconfig;
strncpy(f.ifr_name, if_name, sizeof(f.ifr_name));
if (ioctl(fd, SIOCSHWTSTAMP, &f) < 0) { perror("ioctl"); return -1; }
enable = 1;
if(setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &enable, sizeof(enable)) < 0)
{ perror("setsockopt()"); return -1; }
if(setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPNS, &enable, sizeof(enable)) < 0)
{ perror("setsockopt()"); return -1; }
ts_flags = SOF_TIMESTAMPING_TX_HARDWARE | SOF_TIMESTAMPING_RX_HARDWARE | SOF_TIMESTAMPING_RAW_HARDWARE;
if(setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &ts_flags, sizeof(ts_flags)) < 0)
{ perror("setsockopt()"); return -1; }
tstart =get_tics();
for(;;)
{
uint64_t t = get_tics();
// fprintf(stderr,"T-tstart %ld\n", t-tstart);
if(t - tstart > 1000000ULL)
{
char buf[64];
fprintf(stderr, "Send!");
tstart= t;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(if_ethertype);
sll.sll_pkttype = PACKET_BROADCAST ;
sll.sll_halen = 6;
memcpy(buf, broadcast_addr, 6);
memcpy(buf+6, my_mac, 6);
buf[12] = if_ethertype >> 8;
buf[13] = if_ethertype & 0xff;
write(fd, buf, 64);
// send_with_ts(fd, buf, 64, &sll);
}
poll_tx_timestamp(fd, NULL);
}
}
main()
{
int i;
system("/sbin/rmmod /tmp/wr-minic.ko");
system("/sbin/rmmod /tmp/whiterabbit_vic.ko");
trace_log_stderr();
shw_init();
xpoint_configure();
endpoint_init();
// shw_ad9516_set_output_delay(6, 0, 0);
shw_ad9516_set_output_delay(9, 2, 0);
system("/sbin/insmod /tmp/whiterabbit_vic.ko");
system("/sbin/insmod /tmp/wr-minic.ko");
system("/sbin/ifconfig wru1 hw ether 00:50:fc:96:9b:0e");
system("/sbin/ifconfig wru1 up 192.168.100.100");
// test_rxts_fifo();
// test_tx_timestamps();
}
CC=$(CROSS_COMPILE)gcc
OBJS = ptpd_netif_mch.o ptpd_netif_test.o
LDFLAGS = -lswitchhw -L../../../libswitchhw
CFLAGS = -I. -O2 -I../../../include -DDEBUG -I../../../../kernel/include
OUTPUT = dupa
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT) wru1"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../../settings
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
// Network API for WR-PTPd
#ifndef __PTPD_NETIF_H
#define __PTPD_NETIF_H
#include <stdio.h>
#include <inttypes.h>
#define PTPD_SOCK_RAW_ETHERNET 1
#define PTPD_SOCK_UDP 2
#define PTPD_FLAGS_MULTICAST 0x1
#define PTPD_FLAGS_BIND_TO_PHYS_PORT 0x2
// error codes (to be extended)
#define PTPD_NETIF_OK 0
#define PTPD_NETIF_ERROR -1
#define PTPD_NETIF_NOT_READY -2
#define PTPD_NETIF_NOT_FOUND -3
// GCC-specific
#define PACKED __attribute__((packed))
#define PHYS_PORT_ANY (0xffff)
// Some system-independent definitions
typedef uint8_t mac_addr_t[6];
typedef uint32_t ipv4_addr_t;
// WhiteRabbit socket - it's void pointer as the real socket structure is private and probably platform-specific.
typedef void *wr_socket_t;
// Socket address for ptp_netif_ functions
typedef struct {
// Network interface name (eth0, ...)
char *if_name;
// Socket family (RAW ethernet/UDP)
int family;
// MAC address
mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t mac_dest;
// IP address
ipv4_addr_t ip;
// UDP port
uint16_t port;
// RAW ethertype
uint16_t ethertype;
// physical port to bind socket to
uint16_t physical_port;
} wr_sockaddr_t;
// PTP 10-byte timestamp
PACKED struct _wr_timestamp {
struct {
uint16_t hi;
uint32_t lo;
} seconds; //seconds field (u48)
uint32_t nanoseconds; //nanoseconds field(u32)
struct {
uint32_t f_cntr;
uint32_t r_cntr;
} wr; // whiterabbit raw hardware timestamp
};
typedef struct _wr_timestamp wr_timestamp_t;
// Frame tag type used for gathering TX timestamps
typedef uint32_t wr_frame_tag_t;
/* OK. These functions we'll develop along with network card driver. You can write your own UDP-based stubs for testing purposes. */
// Initialization of network interface:
// - opens devices
// - does necessary ioctls()
int ptpd_netif_init();
// Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
// automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only.
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags, wr_sockaddr_t *bind_addr);
// Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr_t.
// For raw frames, mac/ethertype needs to be provided, for UDP - ip/port.
// Every transmitted frame has assigned a tag value, stored at tag parameter. This value is later used
// for recovering the precise transmit timestamp. If user doesn't need it, tag parameter can be left NULL.
int ptpd_netif_sendto(wr_socket_t *sock, wr_sockaddr_t *to, void *data, size_t data_length, wr_frame_tag_t *tag);
// Polls for transmit timestamp of previously sent frame having tag value specified by tag parameter. Timestamp value is stored in tx_timestamp.
// Return value:
// PTPD_NETIF_OK: tx timestamp gathered correctly
// PTPD_NETIF_NOT_READY: tx timestamp hasn't been yet received from endpoint
// PTPD_NETIF_NOT_FOUND: no timestamp information for frame having given tag
int ptpd_netif_poll_tx_timestamp(wr_socket_t *sock, wr_frame_tag_t tag, wr_timestamp_t *tx_timestamp);
// Receives an UDP/RAW packet. Data is written to (data) and length is returned. Maximum buffer length can be specified
// by data_length parameter. Sender information is stored in structure specified in 'from'. All RXed packets are timestamped and the timestamp
// is stored in rx_timestamp (unless it's NULL).
int ptpd_netif_recvfrom(wr_socket_t *sock, wr_sockaddr_t *from, void *data, size_t data_length, wr_timestamp_t *rx_timestamp);
// Closes the socket.
int ptpd_netif_close_socket(wr_socket_t *sock);
#endif
// Similation of real WR network interface with hardware timestamping. Supports only raw ethernet now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/net_tstamp.h>
#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>
#include <asm/socket.h>
#include "ptpd_netif.h"
const uint8_t tag_trailer_id[] = {0xde, 0xad, 0xbe, 0xef};
#define ETHER_MTU 1518
#define TX_TS_KEEPALIVE 1000000ULL
#define TX_TS_QUEUE_SIZE 128
const mac_addr_t PTP_MULTICAST_MAC[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e};
struct scm_timestamping {
struct timespec systime;
struct timespec hwtimetrans;
struct timespec hwtimeraw;
};
PACKED struct etherpacket {
struct ethhdr ether;
char data[ETHER_MTU];
};
struct tx_timestamp {
int valid;
wr_timestamp_t ts;
uint32_t tag;
uint64_t t_acq;
};
struct my_socket {
int fd;
wr_sockaddr_t bind_addr;
mac_addr_t local_mac;
int if_index;
uint32_t current_tag;
struct tx_timestamp tx_ts_queue[TX_TS_QUEUE_SIZE];
};
static uint64_t get_tics()
{
struct timezone tz = {0, 0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
int ptpd_netif_init()
{
return PTPD_NETIF_OK;
}
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags, wr_sockaddr_t *bind_addr)
{
struct my_socket *s;
struct sockaddr_ll sll;
int fd;
if(sock_type != PTPD_SOCK_RAW_ETHERNET)
return NULL;
struct ifreq f;
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd < 0)
{
perror("socket()");
return NULL;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
// Put the controller in promiscious mode, so it receives everything
strcpy(f.ifr_name, bind_addr->if_name);
if(ioctl(fd, SIOCGIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
f.ifr_flags |= IFF_PROMISC;
if(ioctl(fd, SIOCSIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
// Find the inteface index
strcpy(f.ifr_name, bind_addr->if_name);
ioctl(fd, SIOCGIFINDEX, &f);
sll.sll_ifindex = f.ifr_ifindex;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(bind_addr->ethertype);
sll.sll_halen = 6;
memcpy(sll.sll_addr, bind_addr->mac, 6);
if(bind(fd, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)) < 0)
{
close(fd);
perror("bind()");
return NULL;
}
// timestamping stuff:
int so_timestamping_flags = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
struct ifreq ifr;
struct hwtstamp_config hwconfig;
strncpy(ifr.ifr_name, bind_addr->if_name, sizeof(ifr.ifr_name));
hwconfig.tx_type = HWTSTAMP_TX_ON;
hwconfig.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
ifr.ifr_data = &hwconfig;
if (ioctl(fd, SIOCSHWTSTAMP, &ifr) < 0)
{
perror("SIOCSHWTSTAMP");
return NULL;
}
if(setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &so_timestamping_flags, sizeof(int)) < 0)
{
perror("setsockopt(SO_TIMESTAMPING)");
return NULL;
}
s=malloc(sizeof(struct my_socket));
memset(s, 0, sizeof(struct my_socket));
s->if_index = f.ifr_ifindex;
// get interface MAC address
if (ioctl(fd, SIOCGIFHWADDR, &f) < 0) { perror("ioctl()"); return NULL; }
memcpy(s->local_mac, f.ifr_hwaddr.sa_data, 6);
memcpy(&s->bind_addr, bind_addr, sizeof(wr_sockaddr_t));
s->fd = fd;
s->current_tag = 0;
return (wr_socket_t*)s;
}
int ptpd_netif_sendto(wr_socket_t *sock, wr_sockaddr_t *to, void *data, size_t data_length, wr_frame_tag_t *tag)
{
struct etherpacket pkt;
struct my_socket *s = (struct my_socket *)sock;
struct sockaddr_ll sll;
uint32_t our_tag;
int rval;
char buf[ETHER_MTU+8];
if(s->bind_addr.family != PTPD_SOCK_RAW_ETHERNET)
return -ENOTSUP;
if(data_length > ETHER_MTU-8) return -EINVAL;
if(tag) // user wants the frame tag for retreiving the timestamp: put it at the end of the frame data (ugly hack, but the current linux Timestamping API sucks anyway....)
{
memcpy(pkt.data + data_length, tag_trailer_id, 4);
memcpy(pkt.data + data_length + 4, &s->current_tag, 4);
our_tag = s->current_tag++;
};
memcpy(pkt.ether.h_dest, to->mac, 6);
memcpy(pkt.ether.h_source, s->local_mac, 6);
pkt.ether.h_proto =htons(to->ethertype);
memcpy(pkt.data, data, data_length);
size_t len = data_length + sizeof(struct ethhdr) + (tag ? 8 : 0);
memset(&sll, 0, sizeof(struct sockaddr_ll));
sll.sll_ifindex = s->if_index;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(to->ethertype);
sll.sll_halen = 6;
rval = sendto(s->fd, &pkt, len, 0, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll));
if(rval > 0 && tag) {
*tag = our_tag;
}
return rval;
}
void age_ts_queue(struct my_socket *s)
{
int i;
uint64_t t = get_tics();
for(i=0; i<TX_TS_QUEUE_SIZE; i++)
if(s->tx_ts_queue[i].valid && (t - s->tx_ts_queue[i].t_acq) > TX_TS_KEEPALIVE)
s->tx_ts_queue[i].valid = 0;
}
static void hdump(uint8_t *buf, int size)
{
int i;
printf("Dump: ");
for(i=0;i<size;i++) printf("%02x ", buf[i]);
printf("\n");
}
static void add_tx_timestamp(struct my_socket *s, uint32_t rtag, struct scm_timestamping *hwts, struct sock_extended_err *serr)
{
uint32_t raw_ts =* (uint64_t *) &hwts->hwtimeraw >> 32; // this is white rabbit raw timestamp. NOT a TIMESPEC!
wr_timestamp_t ts;
int done = 0;
int i;
ts.wr.r_cntr = raw_ts & 0xfffffff;
ts.wr.f_cntr = (raw_ts>>28) & 0xf;
for(i=0;i<TX_TS_QUEUE_SIZE;i++)
{
struct tx_timestamp *tt = &s->tx_ts_queue[i];
if(!tt->valid)
{
tt->t_acq = get_tics();
tt->valid = 1;
tt->tag = rtag;
tt->ts = ts;
done = 1;
break;
}
}
if(!done)
fprintf(stderr,"WARNING: TX timestamp queue full\n!");
}
int ptpd_netif_poll_tx_timestamp(wr_socket_t *sock, wr_frame_tag_t tag, wr_timestamp_t *tx_timestamp)
{
char data[ETHER_MTU+8];
struct my_socket *s = (struct my_socket *) sock;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
int res;
uint32_t rtag;
int i;
struct sock_extended_err *serr = NULL;
struct scm_timestamping *sts = NULL;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
res = recvmsg(s->fd, &msg, MSG_ERRQUEUE|MSG_DONTWAIT);
age_ts_queue(s);
if(res < 8) return PTPD_NETIF_NOT_READY;
// hdump(&control, 128);
if(res >= 0)
{
if(memcmp(data + res - 8, tag_trailer_id, 4))
return PTPD_NETIF_NOT_READY;
memcpy(&rtag, data+res-4, 4);
for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
void *dp = CMSG_DATA(cmsg);
// printf("cmsg %x lev %d typ %d len %d\n", cmsg, cmsg->cmsg_level, cmsg->cmsg_type, cmsg->cmsg_len);
if(cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_TX_TIMESTAMP)
serr = (struct sock_extended_err *) dp;
if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING)
sts = (struct scm_timestamping *) dp;
// printf("Serr %x sts %x\n", serr, sts);
if(serr && sts)
{
add_tx_timestamp(s, rtag, sts, serr);
break;
}
}
}
for(i=0;i<TX_TS_QUEUE_SIZE; i++)
{
struct tx_timestamp *tt = &s->tx_ts_queue[i];
if(tt->valid && tt->tag == tag)
{
*tx_timestamp = tt->ts;
tt->valid = 0;
return PTPD_NETIF_OK;
}
}
return 0;
}
int ptpd_netif_recvfrom(wr_socket_t *sock, wr_sockaddr_t *from, void *data, size_t data_length, wr_timestamp_t *rx_timestamp)
{
struct my_socket *s = (struct my_socket *)sock;
struct etherpacket pkt;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
struct scm_timestamping *sts;
int res;
size_t len = data_length + sizeof(struct ethhdr);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = &pkt;
entry.iov_len = len;
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
int ret = recvmsg(s->fd, &msg, MSG_DONTWAIT);
if(ret < 0 && errno==EAGAIN) return 0; // would be blocking
if(ret == -EAGAIN) return 0;
if(ret <= 0) return ret;
memcpy(data, pkt.data, ret - sizeof(struct ethhdr));
from->ethertype = ntohs(pkt.ether.h_proto);
memcpy(from->mac, pkt.ether.h_source, 6);
memcpy(from->mac_dest, pkt.ether.h_dest, 6);
fprintf(stderr, "recvmsg: ret %d\n", ret);
for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
void *dp = CMSG_DATA(cmsg);
if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING)
sts = (struct scm_timestamping *) dp;
}
if(sts && rx_timestamp)
{
uint32_t raw_ts =(* (uint64_t *) &sts->hwtimeraw) >> 32; // this is white rabbit raw timestamp. NOT a TIMESPEC!
rx_timestamp->wr.r_cntr = raw_ts & 0xfffffff;
rx_timestamp->wr.f_cntr = (raw_ts>>28) & 0xf;
}
return ret - sizeof(struct ethhdr);
}
// Similation of real WR network interface with hardware timestamping. Supports only raw ethernet now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ptpd_netif.h"
char *format_mac_addr(mac_addr_t mac)
{
char buf[32];
snprintf(buf,32,"%02x:%02x:%02x:%02x:%02x:%02x", mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return strdup(buf);
}
char *format_wr_timestamp(wr_timestamp_t ts)
{
char buf[64];
snprintf(buf,64, "rising: %09d nsec, failling: %03d nsec", ts.wr.r_cntr * 8, ts.wr.f_cntr * 8);
return strdup(buf);
}
// peer delay multicast address
const mac_addr_t PTP_MULTICAST_PDELAY[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e};
main(int argc, char *argv[])
{
wr_sockaddr_t bindaddr, to_addr, from_addr;
wr_socket_t *sock;
char buf[1518];
int len;
if(argc < 2)
{
printf("usage: %s network_interface. Run me as root!\n\n", argv[0]);
return -1;
}
// Initialize the netif library
ptpd_netif_init();
// Create a PTP socket:
bindaddr.if_name = strdup(argv[1]); // network intarface
bindaddr.family = PTPD_SOCK_RAW_ETHERNET; // socket type
bindaddr.ethertype = 0x88f7; // PTPv2
memset(bindaddr.mac, 0, 6); // bind to any address (e.g. accepting everything which has 88f7 type)
// Create the socket
sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &bindaddr);
// Set destination address
memcpy(to_addr.mac, PTP_MULTICAST_PDELAY, 6);
// and ethertype
to_addr.ethertype = 0x88f7;
for(;;)
{
wr_frame_tag_t tag;
wr_timestamp_t tx_ts, rx_ts;
// Send a frame and get its TX timestamp
ptpd_netif_sendto(sock, &to_addr, buf, 64, &tag);
if(ptpd_netif_poll_tx_timestamp(sock, tag, &tx_ts) == PTPD_NETIF_OK) {
fprintf(stderr, "TX timestamp: %s\n", format_wr_timestamp(tx_ts));
}
sleep(1);
// receive any incoming frames and their timestamps
while( (len = ptpd_netif_recvfrom(sock, &from_addr, buf, 1518, &rx_ts)) > 0)
{
printf("RX frame: from=%s, to=%s, type=0x%04x, timestamp: %s\n",
format_mac_addr(from_addr.mac),
format_mac_addr(from_addr.mac_dest),
from_addr.ethertype,
format_wr_timestamp(rx_ts));
}
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
void clear_screen()
{
printf("\033[2J\033[1;1H");
}
\ No newline at end of file
/*
* This program demonstrates how the various time stamping features in
* the Linux kernel work. It emulates the behavior of a PTP
* implementation in stand-alone master mode by sending PTPv1 Sync
* multicasts once every second. It looks for similar packets, but
* beyond that doesn't actually implement PTP.
*
* Outgoing packets are time stamped with SO_TIMESTAMPING with or
* without hardware support.
*
* Incoming packets are time stamped with SO_TIMESTAMPING with or
* without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
* SO_TIMESTAMP[NS].
*
* Copyright (C) 2009 Intel Corporation.
* Author: Patrick Ohly <patrick.ohly@intel.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include "asm/types.h"
#include "linux/net_tstamp.h"
#include "linux/errqueue.h"
#ifndef SO_TIMESTAMPING
# define SO_TIMESTAMPING 37
# define SCM_TIMESTAMPING SO_TIMESTAMPING
#endif
#ifndef SO_TIMESTAMPNS
# define SO_TIMESTAMPNS 35
#endif
#ifndef SIOCGSTAMPNS
# define SIOCGSTAMPNS 0x8907
#endif
#ifndef SIOCSHWTSTAMP
# define SIOCSHWTSTAMP 0x89b0
#endif
static void usage(const char *error)
{
if (error)
printf("invalid option: %s\n", error);
printf("timestamping interface option*\n\n"
"Options:\n"
" IP_MULTICAST_LOOP - looping outgoing multicasts\n"
" SO_TIMESTAMP - normal software time stamping, ms resolution\n"
" SO_TIMESTAMPNS - more accurate software time stamping\n"
" SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
" SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
" SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
" SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
" SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
" SOF_TIMESTAMPING_SYS_HARDWARE - request reporting of transformed HW time stamps\n"
" SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
" SIOCGSTAMP - check last socket time stamp\n"
" SIOCGSTAMPNS - more accurate socket time stamp\n");
exit(1);
}
static void bail(const char *error)
{
printf("%s: %s\n", error, strerror(errno));
exit(1);
}
static const unsigned char sync[] = {
0x00, 0x01, 0x00, 0x01,
0x5f, 0x44, 0x46, 0x4c,
0x54, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x01, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x01, 0x00, 0x37,
0x00, 0x00, 0x00, 0x08,
0x00, 0x00, 0x00, 0x00,
0x49, 0x05, 0xcd, 0x01,
0x29, 0xb1, 0x8d, 0xb0,
0x00, 0x00, 0x00, 0x00,
0x00, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x00, 0x00, 0x37,
0x00, 0x00, 0x00, 0x04,
0x44, 0x46, 0x4c, 0x54,
0x00, 0x00, 0xf0, 0x60,
0x00, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01,
0x00, 0x00, 0xf0, 0x60,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x04,
0x44, 0x46, 0x4c, 0x54,
0x00, 0x01,
/* fake uuid */
0x00, 0x01,
0x02, 0x03, 0x04, 0x05,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
{
struct timeval now;
int res;
res = sendto(sock, sync, sizeof(sync), 0,
addr, addr_len);
gettimeofday(&now, 0);
if (res < 0)
printf("%s: %s\n", "send", strerror(errno));
else
printf("%ld.%06ld: sent %d bytes\n",
(long)now.tv_sec, (long)now.tv_usec,
res);
}
static void printpacket(struct msghdr *msg, int res,
char *data,
int sock, int recvmsg_flags,
int siocgstamp, int siocgstampns)
{
struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
struct cmsghdr *cmsg;
struct timeval tv;
struct timespec ts;
struct timeval now;
gettimeofday(&now, 0);
printf("%ld.%06ld: received %s data, %d bytes from %s, %d bytes control messages\n",
(long)now.tv_sec, (long)now.tv_usec,
(recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
res,
inet_ntoa(from_addr->sin_addr),
msg->msg_controllen);
for (cmsg = CMSG_FIRSTHDR(msg);
cmsg;
cmsg = CMSG_NXTHDR(msg, cmsg)) {
printf(" cmsg len %d: ", cmsg->cmsg_len);
switch (cmsg->cmsg_level) {
case SOL_SOCKET:
printf("SOL_SOCKET ");
switch (cmsg->cmsg_type) {
case SO_TIMESTAMP: {
struct timeval *stamp =
(struct timeval *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMP %ld.%06ld",
(long)stamp->tv_sec,
(long)stamp->tv_usec);
break;
}
case SO_TIMESTAMPNS: {
struct timespec *stamp =
(struct timespec *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMPNS %ld.%09ld",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
break;
}
case SO_TIMESTAMPING: {
struct timespec *stamp =
(struct timespec *)CMSG_DATA(cmsg);
printf("SO_TIMESTAMPING ");
printf("SW %ld.%09ld ",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
stamp++;
printf("HW transformed %ld.%09ld ",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
stamp++;
printf("HW raw %ld.%09ld",
(long)stamp->tv_sec,
(long)stamp->tv_nsec);
break;
}
default:
printf("type %d", cmsg->cmsg_type);
break;
}
break;
case IPPROTO_IP:
printf("IPPROTO_IP ");
switch (cmsg->cmsg_type) {
case IP_RECVERR: {
struct sock_extended_err *err =
(struct sock_extended_err *)CMSG_DATA(cmsg);
printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
strerror(err->ee_errno),
err->ee_origin,
#ifdef SO_EE_ORIGIN_TIMESTAMPING
err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
"bounced packet" : "unexpected origin"
#else
"probably SO_EE_ORIGIN_TIMESTAMPING"
#endif
);
if (res < sizeof(sync))
printf(" => truncated data?!");
else if (!memcmp(sync, data + res - sizeof(sync),
sizeof(sync)))
printf(" => GOT OUR DATA BACK (HURRAY!)");
break;
}
case IP_PKTINFO: {
struct in_pktinfo *pktinfo =
(struct in_pktinfo *)CMSG_DATA(cmsg);
printf("IP_PKTINFO interface index %u",
pktinfo->ipi_ifindex);
break;
}
default:
printf("type %d", cmsg->cmsg_type);
break;
}
break;
default:
printf("level %d type %d",
cmsg->cmsg_level,
cmsg->cmsg_type);
break;
}
printf("\n");
}
if (siocgstamp) {
if (ioctl(sock, SIOCGSTAMP, &tv))
printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
else
printf("SIOCGSTAMP %ld.%06ld\n",
(long)tv.tv_sec,
(long)tv.tv_usec);
}
if (siocgstampns) {
if (ioctl(sock, SIOCGSTAMPNS, &ts))
printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
else
printf("SIOCGSTAMPNS %ld.%09ld\n",
(long)ts.tv_sec,
(long)ts.tv_nsec);
}
}
static void recvpacket(int sock, int recvmsg_flags,
int siocgstamp, int siocgstampns)
{
char data[256];
struct msghdr msg;
struct iovec entry;
struct sockaddr_in from_addr;
struct {
struct cmsghdr cm;
char control[512];
} control;
int res;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
if (res < 0) {
printf("%s %s: %s\n",
"recvmsg",
(recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
strerror(errno));
} else {
printpacket(&msg, res, data,
sock, recvmsg_flags,
siocgstamp, siocgstampns);
}
}
int main(int argc, char **argv)
{
int so_timestamping_flags = 0;
int so_timestamp = 0;
int so_timestampns = 0;
int siocgstamp = 0;
int siocgstampns = 0;
int ip_multicast_loop = 0;
char *interface;
int i;
int enabled = 1;
int sock;
struct ifreq device;
struct ifreq hwtstamp;
struct hwtstamp_config hwconfig, hwconfig_requested;
struct sockaddr_in addr;
struct ip_mreq imr;
struct in_addr iaddr;
int val;
socklen_t len;
struct timeval next;
so_timestamping_flags = SOF_TIMESTAMPING_TX_HARDWARE;
interface = strdup("wru1");
sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket < 0)
bail("socket");
memset(&device, 0, sizeof(device));
strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
if (ioctl(sock, SIOCGIFADDR, &device) < 0)
bail("getting interface IP address");
memset(&hwtstamp, 0, sizeof(hwtstamp));
strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
hwtstamp.ifr_data = (void *)&hwconfig;
memset(&hwconfig, 0, sizeof(&hwconfig));
hwconfig.tx_type = HWTSTAMP_TX_ON;
hwconfig.rx_filter = HWTSTAMP_FILTER_NONE;
hwconfig_requested = hwconfig;
if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
bail("SIOCSHWTSTAMP");
}
/* bind to PTP port */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(319 /* PTP event port */);
if (bind(sock,
(struct sockaddr *)&addr,
sizeof(struct sockaddr_in)) < 0)
bail("bind");
inet_aton("224.0.1.130", &iaddr);
addr.sin_addr = iaddr;
imr.imr_multiaddr.s_addr = iaddr.s_addr;
imr.imr_interface.s_addr =
((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
&imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
bail("set multicast");
/*
if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
&imr, sizeof(struct ip_mreq)) < 0)
bail("join multicast group");
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
&ip_multicast_loop, sizeof(enabled)) < 0) {
bail("loop multicast");
}
*/
/* set socket options for time stamping */
if (so_timestamp &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
&enabled, sizeof(enabled)) < 0)
bail("setsockopt SO_TIMESTAMP");
if (so_timestampns &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
&enabled, sizeof(enabled)) < 0)
bail("setsockopt SO_TIMESTAMPNS");
if (so_timestamping_flags &&
setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
&so_timestamping_flags,
sizeof(so_timestamping_flags)) < 0)
bail("setsockopt SO_TIMESTAMPING");
/* request IP_PKTINFO for debugging purposes */
/*
if (setsockopt(sock, SOL_IP, IP_PKTINFO,
&enabled, sizeof(enabled)) < 0)
printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
len = sizeof(val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
else
printf("SO_TIMESTAMP %d\n", val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
strerror(errno));
else
printf("SO_TIMESTAMPNS %d\n", val);
if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
strerror(errno));
} else {
printf("SO_TIMESTAMPING %d\n", val);
if (val != so_timestamping_flags)
printf(" not the expected value %d\n",
so_timestamping_flags);
}
*/
/* send packets forever every five seconds */
gettimeofday(&next, 0);
next.tv_sec = (next.tv_sec + 1) / 5 * 5;
next.tv_usec = 0;
while (1) {
struct timeval now;
struct timeval delta;
long delta_us;
int res;
fd_set readfs, errorfs;
gettimeofday(&now, 0);
delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
(long)(next.tv_usec - now.tv_usec);
if (delta_us > 0) {
/* continue waiting for timeout or data */
delta.tv_sec = delta_us / 1000000;
delta.tv_usec = delta_us % 1000000;
FD_ZERO(&readfs);
FD_ZERO(&errorfs);
FD_SET(sock, &readfs);
FD_SET(sock, &errorfs);
printf("%ld.%06ld: select %ldus\n",
(long)now.tv_sec, (long)now.tv_usec,
delta_us);
res = select(sock + 1, &readfs, 0, &errorfs, &delta);
gettimeofday(&now, 0);
printf("%ld.%06ld: select returned: %d, %s\n",
(long)now.tv_sec, (long)now.tv_usec,
res,
res < 0 ? strerror(errno) : "success");
if (res > 0) {
if (FD_ISSET(sock, &readfs))
printf("ready for reading\n");
if (FD_ISSET(sock, &errorfs))
printf("has error\n");
recvpacket(sock, 0,
siocgstamp,
siocgstampns);
recvpacket(sock, MSG_ERRQUEUE,
siocgstamp,
siocgstampns);
}
} else {
/* write one packet */
sendpacket(sock,
(struct sockaddr *)&addr,
sizeof(addr));
next.tv_sec += 5;
continue;
}
}
return 0;
}
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = rtu_test.o
LDFLAGS = -lswitchhw -L../../libswitchhw -L../../libwripc -L../../libptpnetif -lwripc -lptpnetif
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include -I../../libptpnetif -I../../wrsw_hal -I../../libwripc -g
OUTPUT = rtu_test
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
- scp $(OUTPUT) root@192.168.1.6:/tmp
- scp $(OUTPUT) root@192.168.1.13:/tmp
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
/*
-------------------------------------------------------------------------------
-- Title : Routing Table Unit Test Interface
-- Project : White Rabbit Switch
-------------------------------------------------------------------------------
-- File : rtu_test.c
-- Authors : Maciej Lipinski (maciej.lipinski@cern.ch)
-- Company : CERN BE-CO-HT
-- Created : 2010-06-30
-- Last update: 2010-06-30
-- Description: This file stores entire test interface, which includes:
-- - functions used of data entry (VLAN, HCAM, HTAB, CONFIG) in both:
-- simulation and hardware
-- - functions used for request management
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hw/switch_hw.h>
#include <hal_client.h>
#include "wrsw_rtu.h"
#include "rtu_testunit.h"
static volatile struct RTU_WB *RTU;
static volatile struct RTT_WB *RTT;
#define RTU_BANK_SIZE 65536
struct rtu_state {
uint32_t htab[2][RTU_BANK_SIZE];
int current_bank;
};
void zbt_write(uint32_t base, uint32_t *data, size_t nwords)
{
while(RTU->MFIFO_CSR & RTU_MFIFO_CSR_FULL);
RTU->MFIFO_R0 = RTU_MFIFO_R0_AD_SEL;
RTU->MFIFO_R1 = base;
while(nwords--)
{
while(RTU->MFIFO_CSR & RTU_MFIFO_CSR_FULL);
RTU->MFIFO_R0 = 0;
RTU->MFIFO_R1 = *data++;
}
}
void zbt_clear()
{
const int n_words = 65530;
uint32_t *tmp;
tmp = malloc(n_words * 4);
memset(tmp, 0, n_words * 4);
zbt_write(0, tmp, n_words);
free(tmp);
}
void poll_ufifo()
{
if(! (RTU->UFIFO_CSR & RTU_UFIFO_CSR_EMPTY))
{
uint32_t r0, r1, r2, r3, r4;
r0 = RTU->UFIFO_R0;
r1 = RTU->UFIFO_R1;
r2 = RTU->UFIFO_R2;
r3 = RTU->UFIFO_R3;
r4 = RTU->UFIFO_R4;
printf("UFIFO: port %d DstMac %02x:%02x:%02x:%02x:%02x:%02x SrcMac %02x:%02x:%02x:%02x:%02x:%02x ",
RTU_UFIFO_R4_PID_R(r4),
(r1 >> 8) & 0xff,
(r1 >> 0) & 0xff,
(r0 >> 24) & 0xff,
(r0 >> 16) & 0xff,
(r0 >> 8) & 0xff,
(r0 >> 0) & 0xff,
(r3 >> 8) & 0xff,
(r3 >> 0) & 0xff,
(r2 >> 24) & 0xff,
(r2 >> 16) & 0xff,
(r2 >> 8) & 0xff,
(r2 >> 0) & 0xff);
if(r4 & RTU_UFIFO_R4_HAS_VID)
printf("VLAN: %d ", RTU_UFIFO_R4_VID_R(r4));
if(r4 & RTU_UFIFO_R4_HAS_PRIO)
printf("Priority: %d ", RTU_UFIFO_R4_PRIO_R(r4));
printf("\n");
}
}
void poll_test_unit()
{
uint32_t fpr = RTT -> FPR;
uint32_t mask ,port;
for(port = 0, mask = 1; port < 10; port++, mask<<=1)
{
if(! (fpr & mask))
{
volatile uint32_t *rfifo = ((volatile uint32_t *) &RTT->RFIFO_CH0_R0) + port;
volatile uint32_t ent;
while(! (RTT->FPR & mask))
{
ent = *rfifo;
printf("RSP [port %d DPM=%08x prio=%d drop=%d\n", port, RTT_RFIFO_CH0_R0_DPM_R(ent), RTT_RFIFO_CH0_R0_PRIO_R(ent), ent & RTT_RFIFO_CH0_R0_DROP ? 1: 0);
}
}
}
};
void init()
{
if(halexp_client_init() < 0)
{
printf("Oops... Looks like the HAL is not running :( \n\n");
exit(-1);
}
shw_fpga_mmap_init();
RTU = _fpga_base_virt + FPGA_BASE_RTU;
RTT = _fpga_base_virt + FPGA_BASE_RTU_TESTUNIT;
RTU->GCR = RTU_GCR_HT_BSEL | RTU_GCR_G_ENA;
zbt_clear();
RTU->GCR = RTU_GCR_G_ENA;
RTU->PCR0 = RTU_PCR0_LEARN_EN | RTU_PCR0_PASS_ALL | RTU_PCR0_B_UNREC | RTU_PCR0_PRIO_VAL_W(3) | RTU_PCR0_FIX_PRIO;
RTU->PCR1 = RTU_PCR0_LEARN_EN | RTU_PCR0_PASS_ALL | RTU_PCR0_B_UNREC | RTU_PCR0_PRIO_VAL_W(3) | RTU_PCR0_FIX_PRIO;
}
main()
{
init();
for(;;)
{
poll_ufifo();
poll_test_unit();
}
}
\ No newline at end of file
/*
Register definitions for slave core: RTU testing unit
* File : 1.h
* Author : auto-generated by wbgen2 from rtu_testunit_wb.wb
* Created : Mon Nov 1 14:52:06 2010
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE rtu_testunit_wb.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS_RTU_TESTUNIT_WB_WB
#define __WBGEN2_REGDEFS_RTU_TESTUNIT_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: FIFO Polling Register */
/* definitions for register: Interrupt disable register */
/* definitions for field: FIFO Not Empty in reg: Interrupt disable register */
#define RTT_EIC_IDR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt enable register */
/* definitions for field: FIFO Not Empty in reg: Interrupt enable register */
#define RTT_EIC_IER_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt mask register */
/* definitions for field: FIFO Not Empty in reg: Interrupt mask register */
#define RTT_EIC_IMR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt status register */
/* definitions for field: FIFO Not Empty in reg: Interrupt status register */
#define RTT_EIC_ISR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 0' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 0' data output register 0 */
#define RTT_RFIFO_CH0_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH0_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH0_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH0_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 0' data output register 0 */
#define RTT_RFIFO_CH0_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH0_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH0_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH0_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 0' data output register 0 */
#define RTT_RFIFO_CH0_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 1' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 1' data output register 0 */
#define RTT_RFIFO_CH1_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH1_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH1_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH1_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 1' data output register 0 */
#define RTT_RFIFO_CH1_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH1_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH1_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH1_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 1' data output register 0 */
#define RTT_RFIFO_CH1_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 2' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 2' data output register 0 */
#define RTT_RFIFO_CH2_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH2_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH2_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH2_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 2' data output register 0 */
#define RTT_RFIFO_CH2_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH2_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH2_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH2_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 2' data output register 0 */
#define RTT_RFIFO_CH2_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 3' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 3' data output register 0 */
#define RTT_RFIFO_CH3_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH3_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH3_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH3_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 3' data output register 0 */
#define RTT_RFIFO_CH3_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH3_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH3_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH3_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 3' data output register 0 */
#define RTT_RFIFO_CH3_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 4' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 4' data output register 0 */
#define RTT_RFIFO_CH4_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH4_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH4_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH4_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 4' data output register 0 */
#define RTT_RFIFO_CH4_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH4_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH4_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH4_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 4' data output register 0 */
#define RTT_RFIFO_CH4_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 5' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 5' data output register 0 */
#define RTT_RFIFO_CH5_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH5_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH5_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH5_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 5' data output register 0 */
#define RTT_RFIFO_CH5_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH5_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH5_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH5_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 5' data output register 0 */
#define RTT_RFIFO_CH5_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 6' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 6' data output register 0 */
#define RTT_RFIFO_CH6_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH6_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH6_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH6_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 6' data output register 0 */
#define RTT_RFIFO_CH6_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH6_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH6_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH6_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 6' data output register 0 */
#define RTT_RFIFO_CH6_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 7' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 7' data output register 0 */
#define RTT_RFIFO_CH7_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH7_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH7_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH7_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 7' data output register 0 */
#define RTT_RFIFO_CH7_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH7_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH7_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH7_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 7' data output register 0 */
#define RTT_RFIFO_CH7_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 8' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 8' data output register 0 */
#define RTT_RFIFO_CH8_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH8_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH8_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH8_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 8' data output register 0 */
#define RTT_RFIFO_CH8_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH8_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH8_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH8_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 8' data output register 0 */
#define RTT_RFIFO_CH8_R0_DROP WBGEN2_GEN_MASK(14, 1)
/* definitions for register: FIFO 'Response FIFO for RTU channel 9' data output register 0 */
/* definitions for field: Destination port mask in reg: FIFO 'Response FIFO for RTU channel 9' data output register 0 */
#define RTT_RFIFO_CH9_R0_DPM_MASK WBGEN2_GEN_MASK(0, 11)
#define RTT_RFIFO_CH9_R0_DPM_SHIFT 0
#define RTT_RFIFO_CH9_R0_DPM_W(value) WBGEN2_GEN_WRITE(value, 0, 11)
#define RTT_RFIFO_CH9_R0_DPM_R(reg) WBGEN2_GEN_READ(reg, 0, 11)
/* definitions for field: Final priority in reg: FIFO 'Response FIFO for RTU channel 9' data output register 0 */
#define RTT_RFIFO_CH9_R0_PRIO_MASK WBGEN2_GEN_MASK(11, 3)
#define RTT_RFIFO_CH9_R0_PRIO_SHIFT 11
#define RTT_RFIFO_CH9_R0_PRIO_W(value) WBGEN2_GEN_WRITE(value, 11, 3)
#define RTT_RFIFO_CH9_R0_PRIO_R(reg) WBGEN2_GEN_READ(reg, 11, 3)
/* definitions for field: Drop packet flag in reg: FIFO 'Response FIFO for RTU channel 9' data output register 0 */
#define RTT_RFIFO_CH9_R0_DROP WBGEN2_GEN_MASK(14, 1)
PACKED struct RTT_WB {
/* [0x0]: REG FIFO Polling Register */
uint32_t FPR;
/* padding to: 8 words */
uint32_t __padding_0[7];
/* [0x20]: REG Interrupt disable register */
uint32_t EIC_IDR;
/* [0x24]: REG Interrupt enable register */
uint32_t EIC_IER;
/* [0x28]: REG Interrupt mask register */
uint32_t EIC_IMR;
/* [0x2c]: REG Interrupt status register */
uint32_t EIC_ISR;
/* [0x30]: REG FIFO 'Response FIFO for RTU channel 0' data output register 0 */
uint32_t RFIFO_CH0_R0;
/* [0x34]: REG FIFO 'Response FIFO for RTU channel 1' data output register 0 */
uint32_t RFIFO_CH1_R0;
/* [0x38]: REG FIFO 'Response FIFO for RTU channel 2' data output register 0 */
uint32_t RFIFO_CH2_R0;
/* [0x3c]: REG FIFO 'Response FIFO for RTU channel 3' data output register 0 */
uint32_t RFIFO_CH3_R0;
/* [0x40]: REG FIFO 'Response FIFO for RTU channel 4' data output register 0 */
uint32_t RFIFO_CH4_R0;
/* [0x44]: REG FIFO 'Response FIFO for RTU channel 5' data output register 0 */
uint32_t RFIFO_CH5_R0;
/* [0x48]: REG FIFO 'Response FIFO for RTU channel 6' data output register 0 */
uint32_t RFIFO_CH6_R0;
/* [0x4c]: REG FIFO 'Response FIFO for RTU channel 7' data output register 0 */
uint32_t RFIFO_CH7_R0;
/* [0x50]: REG FIFO 'Response FIFO for RTU channel 8' data output register 0 */
uint32_t RFIFO_CH8_R0;
/* [0x54]: REG FIFO 'Response FIFO for RTU channel 9' data output register 0 */
uint32_t RFIFO_CH9_R0;
};
#endif
/*
Register definitions for slave core: Routing Table Unit (RTU)
* File : wrsw_wb_v9.h
* Author : auto-generated by wbgen2 from ../wrsw_rtu_v3.wb
* Created : Thu Jul 8 08:45:02 2010
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE ../wrsw_rtu_v3.wb
DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
*/
#ifndef __WBGEN2_REGDEFS___/WRSW_RTU_V3_WB
#define __WBGEN2_REGDEFS___/WRSW_RTU_V3_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: RTU Global Control Register */
/* definitions for field: Main table bank select in reg: RTU Global Control Register */
#define RTU_GCR_HT_BSEL WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Hash collision table (HCAM) bank select in reg: RTU Global Control Register */
#define RTU_GCR_HCAM_BSEL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: RTU Global Enable in reg: RTU Global Control Register */
#define RTU_GCR_G_ENA WBGEN2_GEN_MASK(2, 1)
/* definitions for register: Aging register for HCAM */
/* definitions for register: Port Control Register 0 */
/* definitions for field: Learning enable in reg: Port Control Register 0 */
#define RTU_PCR0_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 0 */
#define RTU_PCR0_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 0 */
#define RTU_PCR0_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 0 */
#define RTU_PCR0_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 0 */
#define RTU_PCR0_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR0_PRIO_VAL_SHIFT 4
#define RTU_PCR0_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR0_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 0 */
#define RTU_PCR0_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 1 */
/* definitions for field: Learning enable in reg: Port Control Register 1 */
#define RTU_PCR1_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 1 */
#define RTU_PCR1_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 1 */
#define RTU_PCR1_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 1 */
#define RTU_PCR1_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 1 */
#define RTU_PCR1_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR1_PRIO_VAL_SHIFT 4
#define RTU_PCR1_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR1_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 1 */
#define RTU_PCR1_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 2 */
/* definitions for field: Learning enable in reg: Port Control Register 2 */
#define RTU_PCR2_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 2 */
#define RTU_PCR2_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 2 */
#define RTU_PCR2_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 2 */
#define RTU_PCR2_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 2 */
#define RTU_PCR2_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR2_PRIO_VAL_SHIFT 4
#define RTU_PCR2_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR2_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 2 */
#define RTU_PCR2_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 3 */
/* definitions for field: Learning enable in reg: Port Control Register 3 */
#define RTU_PCR3_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 3 */
#define RTU_PCR3_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 3 */
#define RTU_PCR3_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 3 */
#define RTU_PCR3_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 3 */
#define RTU_PCR3_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR3_PRIO_VAL_SHIFT 4
#define RTU_PCR3_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR3_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 3 */
#define RTU_PCR3_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 4 */
/* definitions for field: Learning enable in reg: Port Control Register 4 */
#define RTU_PCR4_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 4 */
#define RTU_PCR4_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 4 */
#define RTU_PCR4_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 4 */
#define RTU_PCR4_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 4 */
#define RTU_PCR4_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR4_PRIO_VAL_SHIFT 4
#define RTU_PCR4_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR4_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 4 */
#define RTU_PCR4_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 5 */
/* definitions for field: Learning enable in reg: Port Control Register 5 */
#define RTU_PCR5_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 5 */
#define RTU_PCR5_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 5 */
#define RTU_PCR5_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 5 */
#define RTU_PCR5_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 5 */
#define RTU_PCR5_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR5_PRIO_VAL_SHIFT 4
#define RTU_PCR5_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR5_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 5 */
#define RTU_PCR5_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 6 */
/* definitions for field: Learning enable in reg: Port Control Register 6 */
#define RTU_PCR6_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 6 */
#define RTU_PCR6_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 6 */
#define RTU_PCR6_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 6 */
#define RTU_PCR6_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 6 */
#define RTU_PCR6_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR6_PRIO_VAL_SHIFT 4
#define RTU_PCR6_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR6_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 6 */
#define RTU_PCR6_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 7 */
/* definitions for field: Learning enable in reg: Port Control Register 7 */
#define RTU_PCR7_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 7 */
#define RTU_PCR7_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 7 */
#define RTU_PCR7_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 7 */
#define RTU_PCR7_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 7 */
#define RTU_PCR7_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR7_PRIO_VAL_SHIFT 4
#define RTU_PCR7_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR7_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 7 */
#define RTU_PCR7_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 8 */
/* definitions for field: Learning enable in reg: Port Control Register 8 */
#define RTU_PCR8_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 8 */
#define RTU_PCR8_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 8 */
#define RTU_PCR8_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 8 */
#define RTU_PCR8_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 8 */
#define RTU_PCR8_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR8_PRIO_VAL_SHIFT 4
#define RTU_PCR8_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR8_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 8 */
#define RTU_PCR8_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Port Control Register 9 */
/* definitions for field: Learning enable in reg: Port Control Register 9 */
#define RTU_PCR9_LEARN_EN WBGEN2_GEN_MASK(0, 1)
/* definitions for field: Pass all packets in reg: Port Control Register 9 */
#define RTU_PCR9_PASS_ALL WBGEN2_GEN_MASK(1, 1)
/* definitions for field: Pass BPDUs in reg: Port Control Register 9 */
#define RTU_PCR9_PASS_BPDU WBGEN2_GEN_MASK(2, 1)
/* definitions for field: Fix priority in reg: Port Control Register 9 */
#define RTU_PCR9_FIX_PRIO WBGEN2_GEN_MASK(3, 1)
/* definitions for field: Priority value in reg: Port Control Register 9 */
#define RTU_PCR9_PRIO_VAL_MASK WBGEN2_GEN_MASK(4, 3)
#define RTU_PCR9_PRIO_VAL_SHIFT 4
#define RTU_PCR9_PRIO_VAL_W(value) WBGEN2_GEN_WRITE(value, 4, 3)
#define RTU_PCR9_PRIO_VAL_R(reg) WBGEN2_GEN_READ(reg, 4, 3)
/* definitions for field: Unrecognized request behaviour in reg: Port Control Register 9 */
#define RTU_PCR9_B_UNREC WBGEN2_GEN_MASK(7, 1)
/* definitions for register: Interrupt disable register */
/* definitions for field: UFIFO Not Empty IRQ in reg: Interrupt disable register */
#define RTU_EIC_IDR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt enable register */
/* definitions for field: UFIFO Not Empty IRQ in reg: Interrupt enable register */
#define RTU_EIC_IER_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt mask register */
/* definitions for field: UFIFO Not Empty IRQ in reg: Interrupt mask register */
#define RTU_EIC_IMR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Interrupt status register */
/* definitions for field: UFIFO Not Empty IRQ in reg: Interrupt status register */
#define RTU_EIC_ISR_NEMPTY WBGEN2_GEN_MASK(0, 1)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 0 */
/* definitions for field: Destination MAC address least-significant part in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 0 */
#define RTU_UFIFO_R0_DMAC_LO_MASK WBGEN2_GEN_MASK(0, 32)
#define RTU_UFIFO_R0_DMAC_LO_SHIFT 0
#define RTU_UFIFO_R0_DMAC_LO_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define RTU_UFIFO_R0_DMAC_LO_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 1 */
/* definitions for field: Destination MAC address most-significant part in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 1 */
#define RTU_UFIFO_R1_DMAC_HI_MASK WBGEN2_GEN_MASK(0, 16)
#define RTU_UFIFO_R1_DMAC_HI_SHIFT 0
#define RTU_UFIFO_R1_DMAC_HI_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define RTU_UFIFO_R1_DMAC_HI_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 2 */
/* definitions for field: Source MAC address least-significant part in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 2 */
#define RTU_UFIFO_R2_SMAC_LO_MASK WBGEN2_GEN_MASK(0, 32)
#define RTU_UFIFO_R2_SMAC_LO_SHIFT 0
#define RTU_UFIFO_R2_SMAC_LO_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define RTU_UFIFO_R2_SMAC_LO_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 3 */
/* definitions for field: Source MAC address most-significant part in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 3 */
#define RTU_UFIFO_R3_SMAC_HI_MASK WBGEN2_GEN_MASK(0, 16)
#define RTU_UFIFO_R3_SMAC_HI_SHIFT 0
#define RTU_UFIFO_R3_SMAC_HI_W(value) WBGEN2_GEN_WRITE(value, 0, 16)
#define RTU_UFIFO_R3_SMAC_HI_R(reg) WBGEN2_GEN_READ(reg, 0, 16)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
/* definitions for field: VLAN Identifier in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
#define RTU_UFIFO_R4_VID_MASK WBGEN2_GEN_MASK(0, 12)
#define RTU_UFIFO_R4_VID_SHIFT 0
#define RTU_UFIFO_R4_VID_W(value) WBGEN2_GEN_WRITE(value, 0, 12)
#define RTU_UFIFO_R4_VID_R(reg) WBGEN2_GEN_READ(reg, 0, 12)
/* definitions for field: Priority in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
#define RTU_UFIFO_R4_PRIO_MASK WBGEN2_GEN_MASK(12, 3)
#define RTU_UFIFO_R4_PRIO_SHIFT 12
#define RTU_UFIFO_R4_PRIO_W(value) WBGEN2_GEN_WRITE(value, 12, 3)
#define RTU_UFIFO_R4_PRIO_R(reg) WBGEN2_GEN_READ(reg, 12, 3)
/* definitions for field: Port ID in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
#define RTU_UFIFO_R4_PID_MASK WBGEN2_GEN_MASK(16, 4)
#define RTU_UFIFO_R4_PID_SHIFT 16
#define RTU_UFIFO_R4_PID_W(value) WBGEN2_GEN_WRITE(value, 16, 4)
#define RTU_UFIFO_R4_PID_R(reg) WBGEN2_GEN_READ(reg, 16, 4)
/* definitions for field: VID valid in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
#define RTU_UFIFO_R4_HAS_VID WBGEN2_GEN_MASK(20, 1)
/* definitions for field: PRIO valid in reg: FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
#define RTU_UFIFO_R4_HAS_PRIO WBGEN2_GEN_MASK(21, 1)
/* definitions for register: FIFO 'Unrecognized request FIFO (UFIFO)' control/status register */
/* definitions for field: FIFO empty flag in reg: FIFO 'Unrecognized request FIFO (UFIFO)' control/status register */
#define RTU_UFIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO counter in reg: FIFO 'Unrecognized request FIFO (UFIFO)' control/status register */
#define RTU_UFIFO_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 7)
#define RTU_UFIFO_CSR_USEDW_SHIFT 0
#define RTU_UFIFO_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 7)
#define RTU_UFIFO_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 7)
/* definitions for register: FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 0 */
/* definitions for field: Address/data select in reg: FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 0 */
#define RTU_MFIFO_R0_AD_SEL WBGEN2_GEN_MASK(0, 1)
/* definitions for register: FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 1 */
/* definitions for field: Address/data value in reg: FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 1 */
#define RTU_MFIFO_R1_AD_VAL_MASK WBGEN2_GEN_MASK(0, 32)
#define RTU_MFIFO_R1_AD_VAL_SHIFT 0
#define RTU_MFIFO_R1_AD_VAL_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define RTU_MFIFO_R1_AD_VAL_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: FIFO 'Main hashtable CPU access FIFO (MFIFO)' control/status register */
/* definitions for field: FIFO full flag in reg: FIFO 'Main hashtable CPU access FIFO (MFIFO)' control/status register */
#define RTU_MFIFO_CSR_FULL WBGEN2_GEN_MASK(16, 1)
/* definitions for field: FIFO empty flag in reg: FIFO 'Main hashtable CPU access FIFO (MFIFO)' control/status register */
#define RTU_MFIFO_CSR_EMPTY WBGEN2_GEN_MASK(17, 1)
/* definitions for field: FIFO counter in reg: FIFO 'Main hashtable CPU access FIFO (MFIFO)' control/status register */
#define RTU_MFIFO_CSR_USEDW_MASK WBGEN2_GEN_MASK(0, 6)
#define RTU_MFIFO_CSR_USEDW_SHIFT 0
#define RTU_MFIFO_CSR_USEDW_W(value) WBGEN2_GEN_WRITE(value, 0, 6)
#define RTU_MFIFO_CSR_USEDW_R(reg) WBGEN2_GEN_READ(reg, 0, 6)
/* definitions for RAM: Hash collisions memory (HCAM) */
#define RTU_HCAM_BYTES 0x00000800 /* size in bytes */
#define RTU_HCAM_WORDS 0x00000200 /* size in 32-bit words, 32-bit aligned */
/* definitions for RAM: Aging bitmap for main hashtable */
#define RTU_ARAM_MAIN_BYTES 0x00000400 /* size in bytes */
#define RTU_ARAM_MAIN_WORDS 0x00000100 /* size in 32-bit words, 32-bit aligned */
/* definitions for RAM: VLAN table (VLAN_TAB) */
#define RTU_VLAN_TAB_BYTES 0x00004000 /* size in bytes */
#define RTU_VLAN_TAB_WORDS 0x00001000 /* size in 32-bit words, 32-bit aligned */
PACKED struct RTU_WB {
/* [0x0]: REG RTU Global Control Register */
uint32_t GCR;
/* [0x4]: REG Aging register for HCAM */
uint32_t AGR_HCAM;
/* [0x8]: REG Port Control Register 0 */
uint32_t PCR0;
/* [0xc]: REG Port Control Register 1 */
uint32_t PCR1;
/* [0x10]: REG Port Control Register 2 */
uint32_t PCR2;
/* [0x14]: REG Port Control Register 3 */
uint32_t PCR3;
/* [0x18]: REG Port Control Register 4 */
uint32_t PCR4;
/* [0x1c]: REG Port Control Register 5 */
uint32_t PCR5;
/* [0x20]: REG Port Control Register 6 */
uint32_t PCR6;
/* [0x24]: REG Port Control Register 7 */
uint32_t PCR7;
/* [0x28]: REG Port Control Register 8 */
uint32_t PCR8;
/* [0x2c]: REG Port Control Register 9 */
uint32_t PCR9;
/* padding to: 16 words */
uint32_t __padding_0[4];
/* [0x40]: REG Interrupt disable register */
uint32_t EIC_IDR;
/* [0x44]: REG Interrupt enable register */
uint32_t EIC_IER;
/* [0x48]: REG Interrupt mask register */
uint32_t EIC_IMR;
/* [0x4c]: REG Interrupt status register */
uint32_t EIC_ISR;
/* [0x50]: REG FIFO 'Unrecognized request FIFO (UFIFO)' data output register 0 */
uint32_t UFIFO_R0;
/* [0x54]: REG FIFO 'Unrecognized request FIFO (UFIFO)' data output register 1 */
uint32_t UFIFO_R1;
/* [0x58]: REG FIFO 'Unrecognized request FIFO (UFIFO)' data output register 2 */
uint32_t UFIFO_R2;
/* [0x5c]: REG FIFO 'Unrecognized request FIFO (UFIFO)' data output register 3 */
uint32_t UFIFO_R3;
/* [0x60]: REG FIFO 'Unrecognized request FIFO (UFIFO)' data output register 4 */
uint32_t UFIFO_R4;
/* [0x64]: REG FIFO 'Unrecognized request FIFO (UFIFO)' control/status register */
uint32_t UFIFO_CSR;
/* [0x68]: REG FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 0 */
uint32_t MFIFO_R0;
/* [0x6c]: REG FIFO 'Main hashtable CPU access FIFO (MFIFO)' data input register 1 */
uint32_t MFIFO_R1;
/* [0x70]: REG FIFO 'Main hashtable CPU access FIFO (MFIFO)' control/status register */
uint32_t MFIFO_CSR;
/* padding to: 4096 words */
uint32_t __padding_1[4067];
/* [0x4000 - 0x47ff]: RAM Hash collisions memory (HCAM), 512 32-bit words, 32-bit aligned, word-addressable */
uint32_t HCAM [512];
/* padding to: 8192 words */
uint32_t __padding_2[4096];
/* [0x8000 - 0x83ff]: RAM Aging bitmap for main hashtable, 256 32-bit words, 32-bit aligned, word-addressable */
uint32_t ARAM_MAIN [256];
/* padding to: 12288 words */
uint32_t __padding_3[4096];
/* [0xc000 - 0xffff]: RAM VLAN table (VLAN_TAB), 4096 32-bit words, 32-bit aligned, word-addressable */
uint32_t VLAN_TAB [4096];
};
#endif
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = spi_test.o
LDFLAGS = -lswitchhw -L../../libswitchhw -L../../libwripc -lwripc
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include -I../../wrsw_hal -I../../libwripc -g
OUTPUT = spi_test
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
- scp $(OUTPUT) root@${T}:/tmp
- ssh -t root@${T} "LD_LIBRARY_PATH=/wr/lib /tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <hw/switch_hw.h>
#include <hw/pio.h>
static const pio_pin_t PIN_sck[] = {{PIOB, 14, PIO_MODE_GPIO, PIO_OUT_1}, {0}};
static const pio_pin_t PIN_cs[] = {{PIOB, 15, PIO_MODE_GPIO, PIO_OUT_1}, {0}};
static const pio_pin_t PIN_sdout[] = {{PIOB, 12, PIO_MODE_GPIO, PIO_OUT_1}, {0}};
static const pio_pin_t PIN_sdin[] = {{PIOB, 13, PIO_MODE_GPIO, PIO_IN}, {0}};
static inline void spi_cs(int val)
{
shw_pio_set(PIN_cs, val);
}
static inline uint8_t spi_txrx(uint8_t x)
{
int i;
uint8_t rval = 0;
for(i=0;i<8;i++)
{
shw_udelay(10);
shw_pio_set(PIN_sdout, x&0x80 ? 1 :0);
shw_udelay(10);
shw_pio_set0(PIN_sck);
shw_udelay(10);
rval <<= 1;
if(shw_pio_get(PIN_sdin)) rval |= 1;
shw_udelay(10);
shw_pio_set1(PIN_sck);
shw_udelay(10);
x<<=1;
}
return rval;
}
void wd_spi_xfer(uint8_t *buf, int size)
{
int i;
spi_cs(0);
for(i=0;i<size;i++)
buf[i]=spi_txrx(buf[i]);
spi_cs(1);
shw_udelay(10);
}
#define WD_CMD_SET_LED 1
#define WD_CMD_FEEDBACK 2
#define LED_LINK 0
#define LED_ACT 1
#define LED_OFF 0
#define LED_ON 1
#define LED_BLINK_SLOW 2
#define LED_BLINK_FAST 3
#define FEEDBACK_TX 1
#define FEEDBACK_RX 2
#define FEEDBACK_OFF 3
void shw_mbl_set_leds(int port, int led, int mode)
{
uint8_t cmd_buf[4];
cmd_buf[0] = WD_CMD_SET_LED;
cmd_buf[1] = port;
cmd_buf[2] = led;
cmd_buf[3] = mode;
wd_spi_xfer(cmd_buf, 4);
}
void shw_mbl_cal_feedback(int port, int cmd)
{
uint8_t cmd_buf[4];
cmd_buf[0] = WD_CMD_FEEDBACK;
cmd_buf[1] = port;
cmd_buf[2] = cmd;
cmd_buf[3] = 0;
wd_spi_xfer(cmd_buf, 4);
}
int main(int argc, char **argv)
{
trace_log_stderr();
shw_pio_mmap_init();
shw_pio_configure(PIN_sck);
shw_pio_configure(PIN_cs);
shw_pio_configure(PIN_sdout);
shw_pio_configure(PIN_sdin);
shw_mbl_set_leds(0, LED_LINK, LED_BLINK_FAST);
// shw_mbl_set_leds(0, LED_LINK, LED_BLINK_SLOW);
for(;;)
{
shw_mbl_cal_feedback(4, FEEDBACK_RX);
sleep(1);
shw_mbl_cal_feedback(4, FEEDBACK_OFF);
sleep(1);
};
}
include ../../../Makedefs
CC=$(CROSS_COMPILE_ARM)gcc
OBJS = hal_client.o sync_test.o ptpd_netif_mch.o
LDFLAGS = -lswitchhw -L../../libswitchhw -L../../libwripc -lwripc
CFLAGS = -I. -O2 -I../../include -DDEBUG -I../../../kernel/include -I../../wrsw_hal -I../../libwripc -g
OUTPUT = sync_test
all: $(OBJS)
make -C ../../libswitchhw
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
- scp $(OUTPUT) root@192.168.1.6:/tmp
- scp $(OUTPUT) root@192.168.1.13:/tmp
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#include <stdio.h>
#include <stdlib.h>
#include "hal_exports.h"
#include <wr_ipc.h>
static wripc_handle_t hal_cli;
int halexp_check_running()
{
//int res_int;
// return wripc_call(hal_ipc, "halexp_check_running", ;
}
int halexp_reset_port(const char *port_name)
{
// TRACE(TRACE_INFO, "resetting port %s\n", port_name);
return 0;
}
int halexp_calibration_cmd(const char *port_name, int command, int on_off)
{
int rval;
wripc_call(hal_cli, "halexp_calibration_cmd", &rval, A_STRING(port_name), A_INT32(command), A_INT32(on_off));
return rval;
}
int halexp_lock_cmd(const char *port_name, int command, int priority)
{
int rval;
wripc_call(hal_cli, "halexp_lock_cmd", &rval, 3, A_STRING(port_name), A_INT32(command), A_INT32(priority));
return rval;
}
int halexp_query_port(char *port_name, int id)
{
}
int halexp_get_port_state(hexp_port_state_t *state, const char *port_name)
{
wripc_call(hal_cli, "halexp_get_port_state", state, 1, A_STRING(port_name));
}
int halexp_pps_cmd(int cmd, hexp_pps_params_t *params)
{
int rval;
wripc_call(hal_cli, "halexp_pps_cmd", &rval, 2, A_INT32(cmd), A_STRUCT(*params));
return rval;
}
int halexp_client_init()
{
hal_cli = wripc_connect(WRSW_HAL_SERVER_ADDR);
if(hal_cli < 0)
return -1;
else
return 0;
}
#ifndef __HAL_CLIENT_H
#define __HAL_CLIENT_H
#include "hal_exports.h"
int halexp_client_init();
#endif
// Network API for WR-PTPd
#ifndef __PTPD_NETIF_H
#define __PTPD_NETIF_H
#include <stdio.h>
#include <inttypes.h>
#define PTPD_SOCK_RAW_ETHERNET 1
#define PTPD_SOCK_UDP 2
#define PTPD_FLAGS_MULTICAST 0x1
#define PTPD_FLAGS_BIND_TO_PHYS_PORT 0x2
// error codes (to be extended)
#define PTPD_NETIF_OK 0
#define PTPD_NETIF_ERROR -1
#define PTPD_NETIF_NOT_READY -2
#define PTPD_NETIF_NOT_FOUND -3
// GCC-specific
#define PACKED __attribute__((packed))
#define PHYS_PORT_ANY (0xffff)
// Some system-independent definitions
typedef uint8_t mac_addr_t[6];
typedef uint32_t ipv4_addr_t;
// WhiteRabbit socket - it's void pointer as the real socket structure is private and probably platform-specific.
typedef void *wr_socket_t;
// Socket address for ptp_netif_ functions
typedef struct {
// Network interface name (eth0, ...)
char if_name[16];
// Socket family (RAW ethernet/UDP)
int family;
// MAC address
mac_addr_t mac;
// Destination MASC address, filled by recvfrom() function on interfaces bound to multiple addresses
mac_addr_t mac_dest;
// IP address
ipv4_addr_t ip;
// UDP port
uint16_t port;
// RAW ethertype
uint16_t ethertype;
// physical port to bind socket to
uint16_t physical_port;
} wr_sockaddr_t;
typedef struct {
uint32_t v[4];
} wr_picoseconds_t;
// PTP 10-byte timestamp
PACKED struct _wr_timestamp {
uint64_t utc;
uint32_t nsec;
int32_t phase; // phase(picoseconds)
int cntr_ahead;
};
typedef struct _wr_timestamp wr_timestamp_t;
// Frame tag type used for gathering TX timestamps
typedef uint32_t wr_frame_tag_t;
/* OK. These functions we'll develop along with network card driver. You can write your own UDP-based stubs for testing purposes. */
// Initialization of network interface:
// - opens devices
// - does necessary ioctls()
int ptpd_netif_init();
// Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
// automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only.
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags, wr_sockaddr_t *bind_addr);
// Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr_t.
// For raw frames, mac/ethertype needs to be provided, for UDP - ip/port.
// Every transmitted frame has assigned a tag value, stored at tag parameter. This value is later used
// for recovering the precise transmit timestamp. If user doesn't need it, tag parameter can be left NULL.
int ptpd_netif_sendto(wr_socket_t *sock, wr_sockaddr_t *to, void *data, size_t data_length, wr_timestamp_t *tx_ts);
// Receives an UDP/RAW packet. Data is written to (data) and length is returned. Maximum buffer length can be specified
// by data_length parameter. Sender information is stored in structure specified in 'from'. All RXed packets are timestamped and the timestamp
// is stored in rx_timestamp (unless it's NULL).
int ptpd_netif_recvfrom(wr_socket_t *sock, wr_sockaddr_t *from, void *data, size_t data_length, wr_timestamp_t *rx_timestamp);
// Closes the socket.
int ptpd_netif_close_socket(wr_socket_t *sock);
#endif
// Similation of real WR network interface with hardware timestamping. Supports only raw ethernet now.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <linux/net_tstamp.h>
#include <linux/errqueue.h>
#include <linux/sockios.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <fcntl.h>
#include <errno.h>
#include <asm/socket.h>
#include "ptpd_netif.h"
const uint8_t tag_trailer_id[] = {0xde, 0xad, 0xbe, 0xef};
#define ETHER_MTU 1518
#define TX_TS_KEEPALIVE 1000000ULL
#define TX_TS_QUEUE_SIZE 128
const mac_addr_t PTP_MULTICAST_MAC[6] = {0x01, 0x80, 0xc2, 0x00, 0x00, 0x0e};
struct scm_timestamping {
struct timespec systime;
struct timespec hwtimetrans;
struct timespec hwtimeraw;
};
PACKED struct etherpacket {
struct ethhdr ether;
char data[ETHER_MTU];
};
struct tx_timestamp {
int valid;
wr_timestamp_t ts;
uint32_t tag;
uint64_t t_acq;
};
struct my_socket {
int fd;
wr_sockaddr_t bind_addr;
mac_addr_t local_mac;
int if_index;
uint32_t current_tag;
struct tx_timestamp tx_ts_queue[TX_TS_QUEUE_SIZE];
};
static uint64_t get_tics()
{
struct timezone tz = {0, 0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + (uint64_t) tv.tv_usec;
}
int ptpd_netif_init()
{
return PTPD_NETIF_OK;
}
wr_socket_t *ptpd_netif_create_socket(int sock_type, int flags, wr_sockaddr_t *bind_addr)
{
struct my_socket *s;
struct sockaddr_ll sll;
int fd;
if(sock_type != PTPD_SOCK_RAW_ETHERNET)
return NULL;
struct ifreq f;
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if(fd < 0)
{
perror("socket()");
return NULL;
}
fcntl(fd, F_SETFL, O_NONBLOCK);
// Put the controller in promiscious mode, so it receives everything
strcpy(f.ifr_name, bind_addr->if_name);
if(ioctl(fd, SIOCGIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
f.ifr_flags |= IFF_PROMISC;
if(ioctl(fd, SIOCSIFFLAGS,&f) < 0) { perror("ioctl()"); return NULL; }
// Find the inteface index
strcpy(f.ifr_name, bind_addr->if_name);
ioctl(fd, SIOCGIFINDEX, &f);
sll.sll_ifindex = f.ifr_ifindex;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(bind_addr->ethertype);
sll.sll_halen = 6;
memcpy(sll.sll_addr, bind_addr->mac, 6);
if(bind(fd, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll)) < 0)
{
close(fd);
perror("bind()");
return NULL;
}
// timestamping stuff:
int so_timestamping_flags = SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
struct ifreq ifr;
struct hwtstamp_config hwconfig;
strncpy(ifr.ifr_name, bind_addr->if_name, sizeof(ifr.ifr_name));
hwconfig.tx_type = HWTSTAMP_TX_ON;
hwconfig.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
ifr.ifr_data = &hwconfig;
if (ioctl(fd, SIOCSHWTSTAMP, &ifr) < 0)
{
perror("SIOCSHWTSTAMP");
return NULL;
}
if(setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING, &so_timestamping_flags, sizeof(int)) < 0)
{
perror("setsockopt(SO_TIMESTAMPING)");
return NULL;
}
s=malloc(sizeof(struct my_socket));
memset(s, 0, sizeof(struct my_socket));
s->if_index = f.ifr_ifindex;
// get interface MAC address
if (ioctl(fd, SIOCGIFHWADDR, &f) < 0) { perror("ioctl()"); return NULL; }
memcpy(s->local_mac, f.ifr_hwaddr.sa_data, 6);
memcpy(&s->bind_addr, bind_addr, sizeof(wr_sockaddr_t));
s->fd = fd;
s->current_tag = 0;
return (wr_socket_t*)s;
}
static int poll_tx_timestamp(wr_socket_t *sock, wr_timestamp_t *tx_timestamp);
int ptpd_netif_sendto(wr_socket_t *sock, wr_sockaddr_t *to, void *data, size_t data_length, wr_timestamp_t *tx_ts)
{
struct etherpacket pkt;
struct my_socket *s = (struct my_socket *)sock;
struct sockaddr_ll sll;
uint32_t our_tag;
int rval;
char buf[ETHER_MTU+8];
wr_timestamp_t ts;
if(s->bind_addr.family != PTPD_SOCK_RAW_ETHERNET)
return -ENOTSUP;
if(data_length > ETHER_MTU-8) return -EINVAL;
memcpy(pkt.ether.h_dest, to->mac, 6);
memcpy(pkt.ether.h_source, s->local_mac, 6);
pkt.ether.h_proto =htons(to->ethertype);
memcpy(pkt.data, data, data_length);
size_t len = data_length + sizeof(struct ethhdr);
memset(&sll, 0, sizeof(struct sockaddr_ll));
sll.sll_ifindex = s->if_index;
sll.sll_family = AF_PACKET;
sll.sll_protocol = htons(to->ethertype);
sll.sll_halen = 6;
rval = sendto(s->fd, &pkt, len, 0, (struct sockaddr *)&sll, sizeof(struct sockaddr_ll));
if(poll_tx_timestamp(s, &ts) > 0)
{
if(tx_ts) memcpy(tx_ts, &ts, sizeof(wr_timestamp_t));
return rval;
}
return rval;
}
void age_ts_queue(struct my_socket *s)
{
int i;
uint64_t t = get_tics();
for(i=0; i<TX_TS_QUEUE_SIZE; i++)
if(s->tx_ts_queue[i].valid && (t - s->tx_ts_queue[i].t_acq) > TX_TS_KEEPALIVE)
s->tx_ts_queue[i].valid = 0;
}
static void hdump(uint8_t *buf, int size)
{
int i;
printf("Dump: ");
for(i=0;i<size;i++) printf("%02x ", buf[i]);
printf("\n");
}
static int poll_tx_timestamp(wr_socket_t *sock, wr_timestamp_t *tx_timestamp)
{
char data[ETHER_MTU+8];
struct my_socket *s = (struct my_socket *) sock;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
int res;
uint32_t rtag;
int i;
struct sock_extended_err *serr = NULL;
struct scm_timestamping *sts = NULL;
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = data;
entry.iov_len = sizeof(data);
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
res = recvmsg(s->fd, &msg, MSG_ERRQUEUE|MSG_DONTWAIT);
if(res <= 0) return PTPD_NETIF_NOT_READY;
if(res >= 0)
{
memcpy(&rtag, data+res-4, 4);
for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
void *dp = CMSG_DATA(cmsg);
// fprintf(stderr, "cmsg %x lev %d typ %d len %d\n", cmsg, cmsg->cmsg_level, cmsg->cmsg_type, cmsg->cmsg_len);
if(cmsg->cmsg_level == SOL_PACKET && cmsg->cmsg_type == PACKET_TX_TIMESTAMP)
serr = (struct sock_extended_err *) dp;
if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING)
sts = (struct scm_timestamping *) dp;
// printf("Serr %x sts %x\n", serr, sts);
if(serr && sts)
{
uint32_t raw_ts =* (uint64_t *) &sts->hwtimeraw >> 32; // this is white rabbit raw timestamp. NOT a TIMESPEC!
// fprintf(stderr,"GotTXTS\n");
tx_timestamp->cntr_ahead = 0;
tx_timestamp->nsec = sts->hwtimeraw.tv_nsec;
tx_timestamp->utc = (uint64_t) sts->hwtimeraw.tv_sec & 0xffff;
return 1;
}
}
}
return 0;
}
int ptpd_netif_recvfrom(wr_socket_t *sock, wr_sockaddr_t *from, void *data, size_t data_length, wr_timestamp_t *rx_timestamp)
{
struct my_socket *s = (struct my_socket *)sock;
struct etherpacket pkt;
struct msghdr msg;
struct iovec entry;
struct sockaddr_ll from_addr;
struct {
struct cmsghdr cm;
char control[1024];
} control;
struct cmsghdr *cmsg;
struct scm_timestamping *sts;
int res;
size_t len = data_length + sizeof(struct ethhdr);
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &entry;
msg.msg_iovlen = 1;
entry.iov_base = &pkt;
entry.iov_len = len;
msg.msg_name = (caddr_t)&from_addr;
msg.msg_namelen = sizeof(from_addr);
msg.msg_control = &control;
msg.msg_controllen = sizeof(control);
int ret = recvmsg(s->fd, &msg, MSG_DONTWAIT);
if(ret < 0 && errno==EAGAIN) return 0; // would be blocking
if(ret == -EAGAIN) return 0;
if(ret <= 0) return ret;
memcpy(data, pkt.data, ret - sizeof(struct ethhdr));
from->ethertype = ntohs(pkt.ether.h_proto);
memcpy(from->mac, pkt.ether.h_source, 6);
memcpy(from->mac_dest, pkt.ether.h_dest, 6);
// fprintf(stderr, "recvmsg: ret %d\n", ret);
for (cmsg = CMSG_FIRSTHDR(&msg);
cmsg;
cmsg = CMSG_NXTHDR(&msg, cmsg)) {
void *dp = CMSG_DATA(cmsg);
if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMPING)
sts = (struct scm_timestamping *) dp;
}
if(sts && rx_timestamp)
{
rx_timestamp->cntr_ahead = sts->hwtimeraw.tv_sec & 0x80000000 ? 1: 0;
rx_timestamp->nsec = sts->hwtimeraw.tv_nsec;
rx_timestamp->utc = (uint64_t) sts->hwtimeraw.tv_sec & 0x7fffffff;
}
return ret - sizeof(struct ethhdr);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/time.h>
#include "ptpd_netif.h"
#include "hal_exports.h"
#include <hw/fpga_regs.h>
#include <hw/pps_gen_regs.h>
#define PPS_GEN_BASE 0x1c0000
#define PTYPE_ANNOUNCE 1
#define PTYPE_ANNOUNCE_RESP 2
#define PTYPE_DELAY_REQ 3
#define PTYPE_DELAY_RESP 4
#define PTYPE_DELAY_REQ_FOLLOWUP 5
#define PTYPE_DELAY_RESP_FOLLOWUP 6
#define PTYPE_CALIBRATION_REQUEST 7
#define PTYPE_CALIBRATION_ACK 8
#define PTYPE_LOCK_REQUEST 9
#define PTYPE_LOCK_ACK 10
#define PATTERN_ON 2
#define GET_DELTAS 3
#define CAL_ERROR -1
typedef struct {
uint64_t utc;
uint32_t nsec;
uint32_t phase;
} timestamp_t;
typedef struct {
int ptype;
int seq;
struct {
wr_timestamp_t t1, t2, t3, t4;
} delay;
struct {
int cmd;
int ack;
int pattern_duration;
uint64_t delta_tx;
uint64_t delta_rx;
int drx_valid, dtx_valid;
} cal;
struct {
int is_master;
} announce;
struct {
int ok;
} announce_resp;
} sync_packet_t;
#define ST_INIT 0
#define ST_WAIT_LINK 1
#define ST_S_WAIT_ANNOUNCE 2
#define ST_M_SEND_ANNOUNCE 3
#define ST_M_CALIBRATE 4
#define ST_S_CALIBRATE 5
#define ST_S_WAIT_COMMAND 6
#define ST_M_WAIT_SLAVE_LOCK 7
#define ST_M_WAIT_CALIBRATE 8
#define ST_S_WAIT_LOCK 9
#define ST_M_SEND_SYNC 10
#define ST_M_SEND_SYNC_FOLLOWUP 11
#define ST_S_WAIT_FOLLOWUP 12
typedef struct
{
uint64_t start_tics;
uint64_t timeout;
} timeout_t ;
uint64_t get_tics()
{
struct timezone tz = {0,0};
struct timeval tv;
gettimeofday(&tv, &tz);
return (uint64_t) tv.tv_sec * 1000000ULL + tv.tv_usec;
}
static inline int tmo_init(timeout_t *tmo, uint32_t milliseconds)
{
tmo->start_tics = get_tics();
tmo->timeout = (uint64_t) milliseconds * 1000ULL;
}
static inline int tmo_restart(timeout_t *tmo)
{
tmo->start_tics = get_tics();
}
static inline int tmo_expired(timeout_t *tmo)
{
return (get_tics() - tmo->start_tics > tmo->timeout);
}
#define ANNOUNCE_INTERVAL 200
#define LINK_POLL_INTERVAL 200
#define CALIBRATION_TIME 1000
#define LOCK_CHECK_INTERVAL 500
#define MASTER_PORT "wru1"
#define SLAVE_PORT "wru1"
#define OUR_ETHERTYPE 0x88f8
#define OUR_MCAST_ADDR { 0x01, 0x80, 0xc2, 0x01, 0x00, 0x00 }
int check_link_up(char *iface)
{
hexp_port_state_t state;
int rval = halexp_get_port_state(&state, iface);
return state.up;
}
wr_timestamp_t tms_sub(wr_timestamp_t a, wr_timestamp_t b)
{
wr_timestamp_t c;
if(a.nsec < b.nsec)
{
c.nsec = 1000000000 + a.nsec - b.nsec;
c.utc = -1;
} else {
c.nsec = a.nsec - b.nsec;
c.utc = 0;
}
c.utc += a.utc - b.utc;
return c;
}
void sync_pkt_send(wr_socket_t *sock, sync_packet_t *pkt, wr_timestamp_t *tx_ts)
{
uint8_t mac[] = OUR_MCAST_ADDR;
wr_sockaddr_t send_addr;
send_addr.ethertype = OUR_ETHERTYPE;
memcpy(send_addr.mac, mac, 6);
ptpd_netif_sendto(sock, &send_addr, pkt, sizeof(sync_packet_t), tx_ts);
}
int sync_pkt_receive(wr_socket_t *sock, sync_packet_t *pkt, wr_timestamp_t *ts)
{
wr_sockaddr_t from;
int nrx = ptpd_netif_recvfrom(sock, &from, pkt, sizeof(sync_packet_t), ts);
return (nrx == sizeof(sync_packet_t) && from.ethertype == OUR_ETHERTYPE);
}
static inline int inside_range(int min, int max, int x)
{
if(min < max)
return (x>=min && x<=max);
else
return (x<=max || x>=min);
}
#define TS_T2 1
#define TS_T4 2
void linearize_timestamp(int ts_type, wr_timestamp_t *ts, uint32_t dmtd_phase, hexp_port_state_t *pstate)
{
int trip_lo, trip_hi;
// "phase" transition: DMTD output value (in picoseconds) at which the transition of rising edge
// TS counter will appear
uint32_t phase_trans;
phase_trans = (ts_type == TS_T2 ? pstate->t2_phase_transition : pstate->t4_phase_transition);
// calculate the range within which falling edge timestamp is stable (no possible transitions)
trip_lo = phase_trans - pstate->clock_period / 4;
if(trip_lo < 0) trip_lo += pstate->clock_period;
trip_hi = phase_trans + pstate->clock_period / 4;
if(trip_hi >= pstate->clock_period) trip_hi -= pstate->clock_period;
// fprintf(stderr,"phase %d dtrans %d period %d\n", dmtd_phase, phase_trans, pstate->clock_period);
if(inside_range(trip_lo, trip_hi, dmtd_phase))
{
// We are within +- 25% range of transition area of rising counter. Take the falling edge counter value
// as the "reliable" one.
ts->nsec -= ts->cntr_ahead ? (pstate->clock_period / 1000) : 0;
// check if the phase is before the counter transition value and eventually increase the counter by 1
// to simulate a timestamp transition exactly at phase_trans DMTD phase value
if(inside_range(trip_lo, phase_trans, dmtd_phase))
ts->nsec += pstate->clock_period / 1000;
}
ts->phase = dmtd_phase - phase_trans - 1;
if(ts->phase < 0) ts->phase += pstate->clock_period;
ts->phase = pstate->clock_period -1 -ts->phase;
}
void master_fsm(char *if_name)
{
int state = ST_INIT;
timeout_t tmo;
wr_socket_t *m_sock;
wr_sockaddr_t sock_addr;
sync_packet_t tx_pkt, rx_pkt;
hexp_port_state_t port_state;
wr_frame_tag_t sync_tag;
wr_timestamp_t sync_t1, sync_t2, sync_t3, sync_t4, rx_ts;
int got_packet;
int seq = 0;
strcpy(sock_addr.if_name, if_name);
sock_addr.family = PTPD_SOCK_RAW_ETHERNET; // socket type
sock_addr.ethertype = OUR_ETHERTYPE;
memset(sock_addr.mac, 0, 6);
m_sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr);
fprintf(stderr,"Running as a master\n");
FILE *f_phlog = fopen("/tmp/phase_log_master", "wb");
for(;;)
{
got_packet = sync_pkt_receive(m_sock, &rx_pkt, &rx_ts);
switch(state)
{
case ST_INIT:
tmo_init(&tmo, LINK_POLL_INTERVAL);
state = ST_WAIT_LINK;
fprintf(stderr, "[master] Waiting for the link to go up");
break;
case ST_WAIT_LINK:
if(tmo_expired(&tmo))
{
if(check_link_up(if_name))
{
fprintf(stderr,"\n[master] Link up.\n");
state = ST_M_SEND_ANNOUNCE;
tmo_init(&tmo, ANNOUNCE_INTERVAL);
} else {
fprintf(stderr, ".");
tmo_restart(&tmo);
}
}
break;
case ST_M_SEND_ANNOUNCE:
if(tmo_expired(&tmo))
{
tx_pkt.ptype = PTYPE_ANNOUNCE;
tx_pkt.announce.is_master = 1;
sync_pkt_send(m_sock, &tx_pkt, NULL);
tmo_restart(&tmo);
}
//check if we've got announce response from the slave
if(got_packet && rx_pkt.ptype == PTYPE_ANNOUNCE_RESP)
{
tx_pkt.ptype = PTYPE_LOCK_REQUEST;
sync_pkt_send(m_sock, &tx_pkt, NULL);
state = ST_M_WAIT_SLAVE_LOCK;
fprintf(stderr,"[master] Got ANNOUNCE_RESP, sending LOCK command.\n");
}
break;
case ST_M_WAIT_SLAVE_LOCK:
{
if(got_packet && rx_pkt.ptype == PTYPE_LOCK_ACK)
{
// state = ST_M_WAIT_CALIBRATE;
state = ST_M_SEND_SYNC;
fprintf(stderr,"[master] Slave ACKed its lock.\n");
tmo_init(&tmo, 10);
}
break;
}
case ST_M_WAIT_CALIBRATE:
{
}
break;
case ST_M_SEND_SYNC:
if(tmo_expired(&tmo))
{
tx_pkt.ptype = PTYPE_DELAY_REQ;
tx_pkt.seq = seq;
sync_pkt_send(m_sock, &tx_pkt, &sync_t1);
tx_pkt.ptype = PTYPE_DELAY_REQ_FOLLOWUP;
tx_pkt.delay.t1 = sync_t1;
tx_pkt.seq = seq;
sync_pkt_send(m_sock, &tx_pkt, NULL);
tmo_restart(&tmo);
seq++;
}
if(got_packet && rx_pkt.ptype == PTYPE_DELAY_RESP)
{
fprintf(stderr,"[master] Send Got DELAY_RESP.\n");
sync_t4 =rx_ts;
halexp_get_port_state(&port_state, if_name);
linearize_timestamp(TS_T4, &sync_t4, port_state.phase_val, &port_state);
} else if(got_packet && rx_pkt.ptype == PTYPE_DELAY_RESP_FOLLOWUP)
{
sync_t3 = rx_pkt.delay.t3;
wr_timestamp_t dt = tms_sub(sync_t4, sync_t3);
fprintf(stderr, "%d %lld %d %d\n", port_state.phase_val, dt.utc, dt.nsec, sync_t4.phase);
fprintf(f_phlog, "%d %lld %d %d\n", port_state.phase_val, dt.utc, dt.nsec, sync_t4.phase);
}
break;
}
usleep(1000);
}
}
/*
#define TS_T2 1
#define TS_T4 2
void linearize_timestamp(wr_timestamp_t *ts, hexp_port_state_t *pstate)
{
int trip_lo, trip_hi;
uint32_t ts_fedge = t2->cntr_ahead * 8 + t2->nsec;
trip_lo = PHASE_TRIP_UP1 - PHASE_MAX/4;
if(trip_lo < 0) trip_lo += PHASE_MAX;
trip_hi = PHASE_TRIP_UP1 + PHASE_MAX/4;
if(trip_hi >= PHASE_MAX) trip_hi -= PHASE_MAX;
if(inside_range(trip_lo, trip_hi, dmtd_val))
{
t2->nsec -= t2->cntr_ahead ? REFCLK_PERIOD : 0;
if(inside_range(trip_lo, PHASE_TRIP_UP1, dmtd_val))
t2->nsec += REFCLK_PERIOD;
// fprintf(stderr,"UseFalling %d", t2->cntr_ahead);
}
t2->phase = dmtd_val - PHASE_TRIP_UP1 - 1;
if(t2->phase < 0) t2->phase += PHASE_MAX;
t2->phase = PHASE_MAX-1-t2->phase;
}
*/
void slave_fsm(char *if_name)
{
int state = ST_INIT;
timeout_t tmo;
wr_socket_t *m_sock;
wr_sockaddr_t sock_addr;
sync_packet_t tx_pkt, rx_pkt;
int got_packet;
hexp_port_state_t port_state;
wr_timestamp_t rx_ts, t1, t2, t3;
int phase = 0;
FILE *f_phlog = fopen("/tmp/phase_log_slave", "wb");
strcpy(sock_addr.if_name, if_name);
sock_addr.family = PTPD_SOCK_RAW_ETHERNET; // socket type
sock_addr.ethertype = OUR_ETHERTYPE;
memset(sock_addr.mac, 0, 6);
m_sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr);
fprintf(stderr,"Running as a slave\n");
for(;;)
{
got_packet = sync_pkt_receive(m_sock, &rx_pkt, &rx_ts);
switch(state)
{
case ST_INIT:
tmo_init(&tmo, LINK_POLL_INTERVAL);
state = ST_WAIT_LINK;
fprintf(stderr, "Waiting for the link to go up");
break;
case ST_WAIT_LINK:
if(tmo_expired(&tmo))
{
if(check_link_up(if_name))
{
fprintf(stderr,"\n[slave] Link up.\n");
state = ST_S_WAIT_ANNOUNCE;
tmo_init(&tmo, ANNOUNCE_INTERVAL);
} else {
fprintf(stderr, ".");
tmo_restart(&tmo);
}
}
break;
case ST_S_WAIT_ANNOUNCE:
if(got_packet && rx_pkt.ptype == PTYPE_ANNOUNCE)
{
tx_pkt.ptype = PTYPE_ANNOUNCE_RESP;
tx_pkt.announce_resp.ok = 1;
fprintf(stderr,"[slave] Got ANNOUNCE message!\n");
sync_pkt_send(m_sock, &tx_pkt, NULL);
halexp_lock_cmd(SLAVE_PORT, HEXP_LOCK_CMD_START, 0);
state = ST_S_WAIT_LOCK;
tmo_init(&tmo, LOCK_CHECK_INTERVAL);
}
break;
case ST_S_WAIT_LOCK:
{
if(tmo_expired(&tmo))
{
tmo_restart(&tmo);
int rval = halexp_lock_cmd(SLAVE_PORT, HEXP_LOCK_CMD_CHECK, 0);
if(rval == HEXP_LOCK_STATUS_LOCKED)
{
fprintf(stderr, "[slave] Port %s locked.\n", if_name);
tx_pkt.ptype = PTYPE_LOCK_ACK;
sync_pkt_send(m_sock, &tx_pkt, NULL);
state = ST_S_WAIT_COMMAND;
tmo_init(&tmo, 500);
}
}
break;
}
case ST_S_WAIT_COMMAND:
if(got_packet && rx_pkt.ptype == PTYPE_DELAY_REQ)
{
state = ST_S_WAIT_FOLLOWUP;
// fprintf(stderr, "[slave] Got DELAY_REQ [seq %d].\n", rx_pkt.seq);
t2 = rx_ts;
} else if(tmo_expired(&tmo))
{
tmo_restart(&tmo);
// fprintf(stderr,"[slave] PhaseVal: %d valid: %d\n", (uint32_t) port_state.phase_val, port_state.phase_val_valid);
}
break;
case ST_S_WAIT_FOLLOWUP:
if(got_packet && rx_pkt.ptype == PTYPE_DELAY_REQ_FOLLOWUP)
{
t1 = rx_pkt.delay.t1;
// fprintf(stderr, "[slave] Got DELAY_REQ_FOLLOWUP [seq %d].\n", rx_pkt.seq);
// fprintf(stderr, "[slave] t1r=%lld.%d t2r=%lld.%d\n", t1.utc, t1.nsec,t2.utc, t2.nsec);
state = ST_S_WAIT_COMMAND;
tx_pkt.ptype = PTYPE_DELAY_RESP;
sync_pkt_send(m_sock, &tx_pkt, &t3);
tx_pkt.ptype = PTYPE_DELAY_RESP_FOLLOWUP;
tx_pkt.delay.t3 = t3;
sync_pkt_send(m_sock, &tx_pkt, NULL);
halexp_get_port_state(&port_state, if_name);
linearize_timestamp(TS_T2, &t2, port_state.phase_val, &port_state);
t1.phase = 0;
wr_timestamp_t dt = tms_sub(t2,t1);
fprintf(stderr, "%d %lld %d %d\n", phase, dt.utc, dt.nsec, t2.phase);
fprintf(f_phlog, "%d %lld %d %d\n", phase, dt.utc, dt.nsec, t2.phase);
fflush(f_phlog);
// increase the phase
hexp_pps_params_t pps_params;
pps_params.adjust_phase_shift = phase;
phase+=10;
halexp_pps_cmd(HEXP_PPSG_CMD_ADJUST_PHASE, &pps_params);
}
break;
}
}
}
main(int argc, char *argv[])
{
if(argc != 3)
{
fprintf(stderr,"Usage: %s [-m/-s] iface\n\n",argv[0]);
return 0;
}
if(halexp_client_init() < 0)
{
fprintf(stderr,"Unable to connect to the WR HAL daemon. Sorry....\n");
return -1;
}
ptpd_netif_init();
if(!strcmp(argv[1], "-m"))
master_fsm(argv[2]);
else if(!strcmp(argv[1], "-s"))
slave_fsm(argv[2]);
else{
fprintf(stderr,"Invalid parameter: %s\n", argv[1]);
return -1;
}
return 0;
}
CC=$(CROSS_COMPILE)gcc
OBJS = test_dacs.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = test_dacs
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run:: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
t=`pwd`
cd ../../libswitchhw
./build.sh clean
./build.sh
cd $t
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
//#include <hw/fpga_io.h>
main()
{
int i=0,di=255,previ=0;
trace_log_stderr();
shw_init();
#if 0
xpoint_test();
for(;;)
{
shw_clkb_dac_write(DAC_REF, i);
shw_clkb_dac_write(DAC_DMTD, i);
i+=di;
if(i<0) {i=0;di=-di;}
else if(i>65530) {i=65530;di=-di;}
}
#endif
shw_clkb_dac_write(DAC_REF, 30000);
shw_clkb_dac_write(DAC_DMTD,30000);
shw_ad9516_set_output_delay(9, 3, 0, 20, 0);
_fpga_writel(FPGA_BASE_GIGASPY_UP1 + GSPY_REG_GSTESTCTL, GSPY_GSTESTCTL_ENABLE | GSPY_GSTESTCTL_CONNECT | GSPY_GSTESTCTL_PHYIO_ENABLE | GSPY_GSTESTCTL_PHYIO_SYNCEN ) ;
printf("TREG: %x\n", _fpga_readl(FPGA_BASE_GIGASPY_UP1 + GSPY_REG_GSTESTCTL));
for(;;)
{
printf("ECnt: %d\n", _fpga_readl(FPGA_BASE_GIGASPY_UP1 + GSPY_REG_GSTESTCNT));
}
}
CC=$(CROSS_COMPILE)gcc
OBJS = test_phys.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = test_phys
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run:: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
t=`pwd`
cd ../../libswitchhw
./build.sh clean
./build.sh
cd $t
make clean
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
#include <stdio.h>
#include <stdarg.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
//#include <hw/fpga_io.h>
#include <sys/time.h>
#define N_PHYS 10
#define CLOCK_TOLLERANCE 2
struct {
uint32_t base;
char * name;
int phy_loopback;
int status_err;
int status_clk;
uint32_t errors, freq;
} ports[] = {
{FPGA_BASE_GIGASPY_UP0, "[up0] uplink0", 0},
{FPGA_BASE_GIGASPY_UP1, "[up1] uplink1", 0},
{FPGA_BASE_GIGASPY_DP0, "[dp0] utca-1", 1},
{FPGA_BASE_GIGASPY_DP1, "[dp1] utca-3", 1},
{FPGA_BASE_GIGASPY_DP2, "[dp2] utca-2", 1},
{FPGA_BASE_GIGASPY_DP3, "[dp3] utca-5", 1},
{FPGA_BASE_GIGASPY_DP4, "[dp4] utca-4", 1},
{FPGA_BASE_GIGASPY_DP5, "[dp5] utca-7", 1},
{FPGA_BASE_GIGASPY_DP6, "[dp6] utca-6", 1},
{FPGA_BASE_GIGASPY_DP7, "[dp7] utca-8", 1},
0
};
#define MEAS_STEPS 20
#define DAC_STEP 10000
#define CLK_REF 0
#define CLK_DMTD 1
#define NUM_CLKB_CLOCKS 4
#define MEAS_DELAY 2
#define N_CLOCKS 4
struct clk_meas {
uint32_t reg;
char *name;
int tunable;
int nominal_freq;
float tuning_range;
uint32_t dac;
int dac_val;
int dac_dval;
int test_steps;
int log_size;
int test_busy;
int dac_ok;
int clock_ok;
int cur_step;
uint32_t prev_step_t;
int have_first_meas;
int vt_log[100];
int freq_log[100];
int dac_val_prev;
float measured_range;
uint32_t cur_freq;
} clocks [] = {
{CLKB_REG_REF_FREQ, "refclk", 1, 125000000, 10e-6, DAC_REF, 0, DAC_STEP, MEAS_STEPS, 0, 1, 0, 0, 0, 0, 0},
{CLKB_REG_DMTD_FREQ, "dmtdclk", 1, 125000000, 100e-6, DAC_DMTD, 65535, -DAC_STEP, MEAS_STEPS, 0, 1, 0, 0, 0, 0, 0},
{CLKB_REG_UP0_FREQ, "up0-clkb", 0, 125000000},
{CLKB_REG_UP1_FREQ, "up1-clkb", 0, 125000000}
};
uint32_t start_tics = 0xffffffff;
uint32_t get_tics()
{
struct timezone tz = {0,0};
struct timeval tv;
gettimeofday(&tv, &tz);
return tv.tv_sec;
}
FILE *clk_log;
void check_dac_vcxo(struct clk_meas *c)
{
int i;
int dv, df;
int fail =0;
double minvt=1000000, maxvt=-1000000;
double minf=200e9, maxf=0;
for(i=0;i<c->cur_step;i++)
{
if(c->freq_log[i] < minf) minf = (double)c->freq_log[i];
if(c->freq_log[i] > maxf) maxf = (double)c->freq_log[i];
if(c->vt_log[i] < minvt) minvt = (double)c->vt_log[i];
if(c->vt_log[i] > maxvt) maxvt = (double)c->vt_log[i];
}
c->measured_range = 0.5 * ( maxf - minf ) * (65536.0 / (maxvt-minvt)) / (double) c->nominal_freq;
fprintf(clk_log, "Clock summary: %s\n", c->name);
fprintf(clk_log, "MeasuredRange: (+/-) %.1f ppm\n", c->measured_range * 1000000.0);
for(i=0;i<c->cur_step;i++)
{
fprintf(clk_log, "vt: %d freq: %d\n", c->vt_log[i], c->freq_log[i]);
if(i>0){
dv = (c->vt_log[i-1] - c->vt_log[i]);
df = (c->freq_log[i-1] - c->freq_log[i]);
if(dv * df <= 0) { fail = 1; } // non-monotonous?
}
}
fflush(clk_log);
c->dac_ok = !fail && (c->measured_range >= c->tuning_range);
}
int meas_remaining_steps;
void check_clock(struct clk_meas *c)
{
if(!c->test_busy || !c->tunable)
{
if(c->tunable) shw_clkb_dac_write(c->dac, 32000);
c->cur_freq = shw_clkb_read_reg(c->reg);
c->clock_ok = ( c->cur_freq > c->nominal_freq - 100000 ) && ( c->cur_freq < c->nominal_freq + 100000 );
} if(c->test_busy && c->prev_step_t + MEAS_DELAY < get_tics())
{
c->prev_step_t = get_tics();
uint32_t freq = shw_clkb_read_reg(c->reg);
c->cur_freq = freq;
shw_clkb_dac_write(c->dac, c->dac_val);
meas_remaining_steps = c->test_steps - c->cur_step;
if(c->have_first_meas)
{
// printf("%s: dac = %d, freq = %d\n", c->name, c->dac_val_prev, freq);
c->freq_log[c->cur_step] = freq;
c->vt_log[c->cur_step] = c->dac_val_prev;
c->cur_step++;
if(c->cur_step == MEAS_STEPS)
{
check_dac_vcxo(c);
meas_remaining_steps = 0;
c->test_busy = 0;
}
}
c->have_first_meas = 1;
c->dac_val_prev = c->dac_val;
c->dac_val += c->dac_dval;
if(c->dac_val <= 0)
{
c->dac_val = 0;
c->dac_dval = -c->dac_dval;
} else if(c->dac_val >= 65535)
{
c->dac_val = 65535;
c->dac_dval = -c->dac_dval;
}
}
}
void update_clkb_clocks()
{
int i;
for(i=0;i<NUM_CLKB_CLOCKS;i++)
{
struct clk_meas *c = &clocks[i];
check_clock(c);
}
}
void cprintf(int color, const char *fmt, ...)
{
va_list ap;
printf("\033[01;3%dm",color);
va_start(ap, fmt);
vprintf(fmt, ap);
va_end(ap);
fflush(stdout);
}
void clear_screen()
{
printf("\033[2J\033[1;1H");
}
#define WHITE 7
#define RED 1
#define GREEN 2
#define BLUE 4
main()
{
int i=0,di=255,previ=0;
trace_log_stderr();
shw_init();
shw_ad9516_set_output_delay(9, 3, 0, 20, 0);
xpoint_configure();
for(i=0;i<N_PHYS;i++)
{
uint32_t flag = GSPY_GSTESTCTL_ENABLE | GSPY_GSTESTCTL_CONNECT | GSPY_GSTESTCTL_PHYIO_ENABLE | GSPY_GSTESTCTL_PHYIO_SYNCEN;
if(ports[i].phy_loopback) flag |= GSPY_GSTESTCTL_PHYIO_LOOPEN;
_fpga_writel(ports[i].base+GSPY_REG_GSTESTCTL, flag) ;
usleep(10000);
uint32_t ctl = _fpga_readl(ports[i].base+GSPY_REG_GSTESTCTL) ; ctl |= GSPY_GSTESTCTL_RST_CNTR; _fpga_writel(ports[i].base+GSPY_REG_GSTESTCTL, ctl);
}
term_init();
clk_log=fopen("clk_meas.log","wb");
for(;;)
{
char c =term_get();
if(c=='q') break;
if(c=='x')
{
clocks[CLK_REF].test_busy=0;
clocks[CLK_DMTD].test_busy=0;
meas_remaining_steps =0;
}
usleep(100000);
clear_screen();
cprintf(BLUE, "PHY/Clocking test program\n----------------------------------\n\n");
update_clkb_clocks();
if(meas_remaining_steps > 0)
{
cprintf(WHITE, "Checking DACs and VCXOs: %d measurements remaining (x = skip).", meas_remaining_steps);
continue;
}
if(clocks[CLK_REF].test_busy || clocks[CLK_DMTD].test_busy) continue;
cprintf(BLUE, "PHY test results:\n\n");
for(i=0;i<N_PHYS;i++)
{
ports[i].freq = _fpga_readl(ports[i].base+GSPY_REG_GSCLKFREQ) ;
ports[i].errors = _fpga_readl(ports[i].base + GSPY_REG_GSTESTCNT);
ports[i].status_err = ports[i].errors > 0;
ports[i].status_clk = abs(ports[i].freq - clocks[CLK_REF].cur_freq) > CLOCK_TOLLERANCE;
cprintf(WHITE, "%-20s: ECNT = %d, RBCLK = %.6f [MHz] status: ", ports[i].name, ports[i].errors, (double)ports[i].freq/1000000.0);
if(ports[i].status_err)
cprintf(RED, "DATA ERRORS ");
if(ports[i].status_clk)
cprintf(RED, "FAULTY RBCLK ");
if(!ports[i].status_clk && !ports[i].status_err)
cprintf(GREEN, "OK ");
printf("\n");
}
cprintf(BLUE, "\nClocking system test results:\n\n");
for(i=0;i<N_CLOCKS;i++)
{
struct clk_meas *c= &clocks[i];
if(c->tunable)
{
cprintf(WHITE, "%-10s: ", c->name);
cprintf(WHITE, "freq: %.6f [MHz] (", (double)c->cur_freq/1000000.0);
if(c->clock_ok) cprintf(GREEN, "OK") ; else cprintf(RED, "FAIL");
cprintf(WHITE, ") DAC/VCXO tuning: ");
if(c->dac_ok) cprintf(GREEN, "OK") ; else cprintf(RED, "FAIL");
cprintf(WHITE, ", range: \xc2\xb1%.1f ppm\n", c->measured_range * 1000000.0);
} else {
cprintf(WHITE, "%-10s: ", c->name);
cprintf(WHITE, "freq: %.6f [MHz] (", (double)c->cur_freq/1000000.0);
if(c->clock_ok) cprintf(GREEN, "OK") ; else cprintf(RED, "FAIL");
cprintf(WHITE,")\n");
}
}
cprintf(BLUE, "\n\n------------------------------\nq = quit");
fflush(stdout);
}
fclose(clk_log);
printf("\033[00;37m");
printf("\n\n");
fflush(stdout);
term_restore();
}
CC=$(CROSS_COMPILE)gcc
OBJS = vic_test.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = vic_test
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) driver/whiterabbit_vic.ko root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
cd driver
./build.sh
cd ..
cd ../../libswitchhw
./build.sh
cd ../tests/vic_test
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
#include <stdio.h>
#include <inttypes.h>
#include <sys/time.h>
#include <signal.h>
#include <hw/switch_hw.h>
#include <hw/clkb_io.h>
#define PIN_IRQ0 25
#define PIN_IRQ3 24
static const pio_pin_t PIN_irq0[] = {{PIO_FPGA, 25, PIO_MODE_GPIO, PIO_OUT_0}, {0}};
static const pio_pin_t PIN_irq3[] = {{PIO_FPGA, 24, PIO_MODE_GPIO, PIO_OUT_0}, {0}};
/* [0x0]: REG VIC Control Register */
#define VIC_REG_CTL 0x00000000
/* [0x4]: REG Raw Interrupt Status Register */
#define VIC_REG_RISR 0x00000004
/* [0x8]: REG Interrupt Enable Register */
#define VIC_REG_IER 0x00000008
/* [0xc]: REG Interrupt Disable Register */
#define VIC_REG_IDR 0x0000000c
/* [0x10]: REG Interrupt Mask Register */
#define VIC_REG_IMR 0x00000010
/* [0x14]: REG Vector Address Register */
#define VIC_REG_VAR 0x00000014
#define VIC_REG_SWIR 0x00000018
#define VIC_REG_EOIR 0x0000001c
#define VIC_CTL_ENABLE (1<<0)
#define VIC_CTL_POL (1<<1)
#define VIC_IVT_BASE 0x00000080
#define FPGA_BASE_VIC 0x60000
main()
{
int i;
trace_log_stderr();
shw_init();
shw_pio_configure(PIN_irq0);
shw_pio_configure(PIN_irq3);
system("/sbin/insmod /tmp/whiterabbit_vic.ko");
_fpga_writel(FPGA_BASE_VIC+VIC_REG_SWIR, 8);
system("/sbin/rmmod whiterabbit_vic");
}
/*
_fpga_writel(FPGA_BASE_VIC+VIC_REG_CTL, VIC_CTL_POL);
printf("VAR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_VAR));
_fpga_writel(FPGA_BASE_VIC+VIC_REG_IDR, 0xffffffff);
int i;
for(i=0;i<32;i++)
_fpga_writel(FPGA_BASE_VIC+VIC_IVT_BASE + (i*4), i+1);
_fpga_writel(FPGA_BASE_VIC+VIC_REG_IER, 8+1);
_fpga_writel(FPGA_BASE_VIC+VIC_REG_CTL, VIC_CTL_POL | VIC_CTL_ENABLE);
printf("IRQ line status: %d\n", shw_pio_get(PIN_cpu_irq0));
printf("RISR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_RISR));
printf("IMR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_IMR));
shw_pio_set0(PIN_irq0);
shw_pio_set0(PIN_irq3);
for(i=0;i<10;i++)
{
printf("IRQ line status: %d\n", shw_pio_get(PIN_cpu_irq0));
}
printf("VAR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_VAR));
shw_pio_set0(PIN_irq0);
_fpga_writel(FPGA_BASE_VIC + VIC_REG_EOIR, 0);
printf("VAR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_VAR));
shw_pio_set0(PIN_irq3);
_fpga_writel(FPGA_BASE_VIC + VIC_REG_EOIR, 0);
printf("VAR: %x\n", _fpga_readl(FPGA_BASE_VIC + VIC_REG_VAR));
*/
CC=$(CROSS_COMPILE)gcc
OBJS = zbt_test.o term.o
LDFLAGS = -lswitchhw -L../../libswitchhw
CFLAGS = -I. -O2 -I../../include -DDEBUG
OUTPUT = zbt_test
all: $(OBJS)
${CC} -o $(OUTPUT) $(OBJS) $(LDFLAGS)
%.o: %.c
${CC} -c $^ $(CFLAGS)
run: all
scp $(OUTPUT) root@$(T):/tmp
- ssh -t root@$(T) "/tmp/$(OUTPUT)"
install: all
mkdir -p ../../rootfs_override/root/tests
cp $(OUTPUT) ../../rootfs_override/root/tests
clean:
rm -f $(OUTPUT) $(OBJS)
\ No newline at end of file
#!/bin/sh
. ../../../settings
make CROSS_COMPILE=$CC_CPU $1 $2 $3 $4
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <poll.h>
struct termios oldkey, newkey;
int term_restore()
{
tcsetattr(STDIN_FILENO,TCSANOW,&oldkey);
}
void term_init()
{
fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
tcgetattr(STDIN_FILENO,&oldkey);
memcpy(&newkey, &oldkey, sizeof(struct termios));
newkey.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
newkey.c_iflag = IGNPAR;
newkey.c_oflag = OPOST |ONLCR;
newkey.c_lflag = 0;
newkey.c_cc[VMIN]=1;
newkey.c_cc[VTIME]=0;
tcflush(STDIN_FILENO, TCIFLUSH);
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
atexit(term_restore);
}
int term_poll()
{
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN | POLLPRI;
if(poll(&pfd,1,0)>0)return 1;
return 0;
}
int term_get()
{
unsigned char c;
int q;
if(read(STDIN_FILENO, &c, 1 ) == 1)
{
q=c;
} else q=-1;
return q;
}
/* ZBT test program */
/* Firmware. MAIN: zbt_test, CLKB: new_wishbone_bridge */
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/time.h>
#include <hw/switch_hw.h>
#define BASE_ZBT 0x40000
void test_the_zbt()
{
int i;
int iter=0;
for(;;)
{
//write some random data
srand(iter*1231931+31231);
for(i=0;i<32768;i++)
{
_fpga_writel(BASE_ZBT + i*4, random()&0xffffffff);
}
// read it out, and verify
srand(iter*1231931+31231);
for(i=0;i<32768;i++)
{
uint32_t rv = _fpga_readl(BASE_ZBT + i*4);
uint32_t v = random()&0xffffffff;
if(v!=rv) { printf("ERROR: V %08x RV %08x XOR %08x\n", v,rv,v^rv); }
}
iter++;
fprintf(stderr,".");
}
}
main()
{
trace_log_stderr();
shw_init();
printf("Testing the ZBT memory...");
test_the_zbt();
return 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