Commit b8c0d875 authored by Vincent van Beveren's avatar Vincent van Beveren

Merge branch 'peter_clbv2_km3net' of https://ohwr.org/project/wrpc-sw into peter_clbv2_km3net

parents 30fbaeb4 ecaae30f
before_script:
- export PATH=/opt/lm32-gcc-4.5.3/bin:$PATH
stages:
- make_wrpc_sw
- make_rt_cpu
make_wrpc_sw:
stage: make_wrpc_sw
script:
- git submodule init; git submodule update
- make spec_defconfig
- make
artifacts:
name: WRPC_SW_CI_%CI_JOB_ID%
paths:
- wrc.bin
- wrc.elf
- wrc.bram
- wrc.mif
make_rt_cpu:
stage: make_rt_cpu
script:
- git submodule init; git submodule update
- make wr_switch_defconfig
- make
artifacts:
name: WRPC_SW_CI_%CI_JOB_ID%
paths:
- rt_cpu.elf
[submodule "ppsi"]
path = ppsi
url = https://ohwr.org/project/ppsi.git
\ No newline at end of file
url = https://ohwr.org/project/ppsi.git
......@@ -36,9 +36,9 @@ config TEMP_HIGH_THRESHOLD
config TEMP_HIGH_RAPPEL
int
default 60
config PLL_VERBOSE
boolean
default y if WR_SWITCH
config PFILTER_VERBOSE
boolean
......@@ -127,8 +127,17 @@ config P2P
If you deny this option, P2P code is not built, to save some
binary size.
config IP
config WR_NIC_CPU
depends on WR_NODE
boolean "Allows compatibility with external NIC driver on CPU"
default n
help
ARP & ICMP traffic are bypassed to the external fabric (NIC) so
that the CPU handles these packets and not the LM32. (This option
is mainly used by the wr-starting-kit on SPEC cards)
config IP
depends on WR_NODE && !WR_NIC_CPU
boolean "Compile minimal IP support in wrpc-sw"
help
This allows to run LM32 code that is aware of IP. The feature is
......@@ -175,13 +184,28 @@ config SNMP_SET
help
This option enables support for SET requests for Mini SNMP responder
config SNMP_INIT
depends on SNMP && BUILD_INIT
default y if BUILD_INIT
default n
boolean "Adds support of changing init script/commands via SNMP"
help
This option adds a branch wrpcInitScriptConfigGroup to the SNMP
config SNMP_SDB
depends on SNMP && GENSDBFS
default y
boolean "Adds support of generation of SDB via SNMP"
help
This option adds a branch wrpcSdbGroup to the SNMP
config SNMP_AUX_DIAG
depends on SNMP && AUX_DIAG
default y if AUX_DIAG
default n
boolean "Adds support of auxiliary diagnostics registers to SNMP"
help
This option adds branch wrpcAuxDiag to the SNMP
This option adds a branch wrpcAuxDiag to the SNMP
config BUILD_INIT
depends on WR_NODE
......@@ -298,7 +322,7 @@ config ABSCAL
described and documented by Peter Jansweijer.
config LLDP
depends on WR_NODE
depends on WR_NODE && IP
boolean "Include LLDP protocol transmit-only"
default n
help
......@@ -487,8 +511,7 @@ config PLL_VERBOSE
depends on DEVELOPER
boolean "Verbose messages in softpll"
help
The softpll is usually silent in WR node and verbose in WR
switch. You can enable pll messages in WR node for debugging.
Outputs additional debugging messages in the softpll. Off by default.
config PFILTER_VERBOSE
depends on DEVELOPER
......
......@@ -10,8 +10,8 @@ CONFIG_RAMSIZE=65536
CONFIG_TEMP_POLL_INTERVAL=15
CONFIG_TEMP_HIGH_THRESHOLD=70
CONFIG_TEMP_HIGH_RAPPEL=60
CONFIG_PLL_VERBOSE=y
CONFIG_WRC_VERBOSE=y
CONFIG_PLL_VERBOSE=n
CONFIG_WRC_VERBOSE=n
CONFIG_VLAN_NR=0
CONFIG_VLAN_1_FOR_CLASS7=0
CONFIG_VLAN_2_FOR_CLASS7=0
......
......@@ -24,21 +24,18 @@ CONFIG_PPSI=y
CONFIG_W1=y
CONFIG_LATENCY_ETHTYPE=291
# CONFIG_P2P is not set
CONFIG_IP=y
CONFIG_WR_NIC_CPU=y
# CONFIG_CMD_CONFIG is not set
# CONFIG_SYSLOG is not set
CONFIG_SNMP=y
CONFIG_SNMP_SET=y
CONFIG_BUILD_INIT=y
CONFIG_INIT_COMMAND="vlan off;ptp stop;sfp match;mode slave;ptp start"
CONFIG_HAS_BUILD_INIT=1
CONFIG_HAS_FLASH_INIT=1
CONFIG_FLASH_INIT=y
# CONFIG_AUX_DIAG is not set
CONFIG_AUX_DIAG=y
CONFIG_SDB_STORAGE=y
CONFIG_GENSDBFS=y
# CONFIG_LEGACY_EEPROM is not set
# CONFIG_WR_DIAG is not set
CONFIG_WR_DIAG=y
# CONFIG_WR_NODE_SIM is not set
CONFIG_ABSCAL=y
......
This diff is collapsed.
......@@ -143,10 +143,85 @@ const struct ad9516_reg ad9516_base_config_34[] = {
{0x0231, 0x00},
};
/* Configuration for the SCB version greater than or equal 3.4: Base + 6, 7, 8, 9 outputs*/
const struct ad9516_reg ad9516_ljd_base_config[] = {
{0x0000, 0x99},
{0x0001, 0x00},
{0x0002, 0x10},
{0x0003, 0xC3},
{0x0004, 0x00},
{0x0010, 0x4C},
{0x0011, 0x00},
{0x0012, 0x00},
{0x0013, 0x06},
{0x0014, 0x12},
{0x0015, 0x00},
{0x0016, 0x04},
{0x0017, 0x00},
{0x0018, 0x07},
{0x0019, 0x00},
{0x001A, 0x00},
{0x001B, 0x00},
{0x001C, 0x01},
{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, 0x08},
{0x00F5, 0x08},
// The following registers configure the PLL outputs from 6 to 9.
{0x0140, 0x42},
{0x0141, 0x42},
{0x0142, 0x08},
{0x0143, 0x4E},
{0x0190, 0x55},
{0x0191, 0x00},
{0x0192, 0x00},
{0x0193, 0x11},
{0x0194, 0x00},
{0x0195, 0x00},
{0x0196, 0x10},
{0x0197, 0x00},
{0x0198, 0x00},
{0x0199, 0x33},
{0x019A, 0x00},
{0x019B, 0x11},
{0x019C, 0x20},
{0x019D, 0x00},
{0x019E, 0x33},
{0x019F, 0x00},
{0x01A0, 0x11},
{0x01A1, 0x20},
{0x01A2, 0x00},
{0x01A3, 0x00},
//
{0x01E0, 0x01},
{0x01E1, 0x02},
{0x0230, 0x00},
{0x0231, 0x00},
};
/* Config for 25 MHz VCTCXO reference (RDiv = 5, use REF1) */
const struct ad9516_reg ad9516_ref_tcxo[] = {
{0x0011, 0x05},
{0x0012, 0x00}, /* RDiv = 5 */
{0x0012, 0x00}, /* RDiv = 4 */
{0x001C, 0x06} /* Use REF1 */
};
......@@ -157,3 +232,9 @@ const struct ad9516_reg ad9516_ref_ext[] = {
{0x001C, 0x46} /* Use REF1 */
};
/* Config for Low-Jitter Daughterboard */
const struct ad9516_reg ad9516_ref_ljd[] = {
{0x0011, 0x04},
{0x0012, 0x00}, /* RDiv = 4 */
{0x001C, 0x06} /* Use REF1 */
};
......@@ -13,7 +13,8 @@ obj-$(CONFIG_EMBEDDED_NODE) += \
dev/devicelist.o \
dev/wrx_wrpc.o \
dev/rxts_calibrator.o \
dev/flash.o
dev/flash.o \
dev/fram.o
obj-$(CONFIG_WR_NODE) += \
dev/temperature.o \
......
......@@ -17,7 +17,7 @@
/*
* Delay function - limit SPI clock speed to 10 MHz
*/
static void delay(void)
void delay(void)
{
int i;
......@@ -28,7 +28,7 @@ static void delay(void)
/*
* Bit-bang SPI transfer function
*/
static uint8_t bbspi_transfer(int cspin, uint8_t val)
uint8_t bbspi_transfer(int cspin, uint8_t val)
{
int i;
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <wrc.h>
#include <fram.h>
#include <types.h>
#include <storage.h>
#include <flash.h>
#define SDBFS_BIG_ENDIAN
#include <libsdbfs.h>
/*
* Init function (just set the SPI pins for idle)
*/
void fram_init(void)
{
//flash_init(); //ML: it is the same as flash, so no need to call it
}
/*
* Write data to flash chip
*/
int fram_write(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x06); // WREN (set write enable latch)
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x02); // optcode for writing
bbspi_transfer(0, (addr & 0xFF00) >> 8);// write address MSB
bbspi_transfer(0, (addr & 0xFF)); // write address LSB
for (i = 0; i < count; i++) {
bbspi_transfer(0, buf[i]);
}
bbspi_transfer(1, 0);
return count;
}
/*
* Read data from flash
*/
int fram_read(uint32_t addr, uint8_t *buf, int count)
{
int i;
bbspi_transfer(1, 0); // idle (possibly not needed)
bbspi_transfer(0, 0x03); // optcode for reading
bbspi_transfer(0, (addr & 0xFF00) >> 8);
bbspi_transfer(0, (addr & 0xFF));
for (i = 0; i < count; i++) {
buf[i] = bbspi_transfer(0, 0);
}
bbspi_transfer(1, 0);
return count;
}
int fram_erase(uint32_t addr, int count)
{
int i;
uint8_t buf[1] = {0xff};
for (i = 0; i < count; i++)
fram_write(addr+i, buf , 1);
return count;
}
/*****************************************************************************/
/* SDB */
/*****************************************************************************/
/* The sdb filesystem itself */
static struct sdbfs wrc_sdb = {
.name = "wrpc-storage",
.blocksize = 0, /* Not currently used */
/* .read and .write according to device type */
};
/*
* SDB read and write functions
*/
static int sdb_fram_read(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_read(offset, buf, count);
}
static int sdb_fram_write(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_write(offset, buf, count);
}
/*
* A trivial dumper, just to show what's up in there
*/
static void fram_sdb_list(struct sdbfs *fs)
{
struct sdb_device *d;
int new = 1;
while ((d = sdbfs_scan(fs, new)) != NULL) {
d->sdb_component.product.record_type = '\0';
pp_printf("file 0x%08x @ %4i, name %19s\n",
(int)(d->sdb_component.product.device_id),
(int)(d->sdb_component.addr_first),
(char *)(d->sdb_component.product.name));
new = 0;
}
}
/*
* Check for SDB presence on fram
*/
int fram_sdb_check(void)
{
uint32_t magic = 0;
int i;
uint32_t entry_point[] = {
0x000000, /* fram base */
0x6000 /* for VXS*/
};
for (i = 0; i < ARRAY_SIZE(entry_point); i++) {
fram_read(entry_point[i], (uint8_t *)&magic, 4);
if (magic == SDB_MAGIC)
break;
}
if (i == ARRAY_SIZE(entry_point))
return -1;
pp_printf("Found SDB magic at address 0x%06x\n", entry_point[i]);
wrc_sdb.drvdata = NULL;
wrc_sdb.entrypoint = entry_point[i];
wrc_sdb.read = sdb_fram_read;
wrc_sdb.write = sdb_fram_write;
fram_sdb_list(&wrc_sdb);
return 0;
}
......@@ -22,6 +22,7 @@
#define SDBFS_BIG_ENDIAN
#include <libsdbfs.h>
#include <flash.h>
#include <fram.h>
/*
* This source file is a drop-in replacement of the legacy one: it manages
......@@ -55,6 +56,22 @@ static int sdb_flash_erase(struct sdbfs *fs, int offset, int count)
return flash_erase(offset, count);
}
/* Functions for FRAM access */
static int sdb_fram_read(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_read(offset, buf, count);
}
static int sdb_fram_write(struct sdbfs *fs, int offset, void *buf, int count)
{
return fram_write(offset, buf, count);
}
static int sdb_fram_erase(struct sdbfs *fs, int offset, int count)
{
return fram_erase(offset, count);
}
/* The methods for W1 access */
static int sdb_w1_read(struct sdbfs *fs, int offset, void *buf, int count)
{
......@@ -211,6 +228,11 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
0x170000, /* after first FPGA bitstream */
0x2e0000, /* after MultiBoot bitstream */
0x600000}; /* after SVEC AFPGA bitstream */
uint32_t entry_points_fram[] = {
0x000000, /* fram base */
0x6000,
0x7000
};
int i, ret;
/*
......@@ -233,9 +255,27 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
goto found_exit;
}
/*
* 2. Look for w1 first: if there is no eeprom it fails fast
* 2. Check if there is SDBFS in the FRAM.
*/
for (i = 0; i < ARRAY_SIZE(entry_points_fram); i++) {
fram_read(entry_points_fram[i], (void *)&magic, sizeof(magic));
if (magic == SDB_MAGIC)
break;
}
if (magic == SDB_MAGIC) {
pp_printf("sdbfs: found at %i in Fram\n",
entry_points_fram[i]);
wrc_sdb.drvdata = NULL;
wrc_sdb.blocksize = 0;
wrc_sdb.entrypoint = entry_points_fram[i];
wrc_sdb.read = sdb_fram_read;
wrc_sdb.write = sdb_fram_write;
wrc_sdb.erase = sdb_fram_erase;
goto found_exit;
}
/*
* 3. Look for w1 first: if there is no eeprom it fails fast
*/
for (i = 0; i < ARRAY_SIZE(entry_points_eeprom); i++) {
ret = w1_read_eeprom_bus(&wrpc_w1_bus, entry_points_eeprom[i],
......@@ -258,7 +298,7 @@ void storage_init(int chosen_i2cif, int chosen_i2c_addr)
}
/*
* 3. If w1 failed, look for i2c: start from low offsets.
* 4. If w1 failed, look for i2c: start from low offsets.
*/
i2c_params.ifnum = chosen_i2cif;
i2c_params.addr = EEPROM_START_ADR;
......@@ -310,9 +350,9 @@ found_exit:
*/
int get_persistent_mac(uint8_t portnum, uint8_t *mac)
{
int ret;
int i, class;
uint64_t rom;
int ret = 0;
int i;
struct w1_dev *d;
if (IS_HOST_PROCESS) {
/* we don't have sdb working, so get the real eth address */
......@@ -321,10 +361,12 @@ int get_persistent_mac(uint8_t portnum, uint8_t *mac)
}
if (sdbfs_open_id(&wrc_sdb, SDB_VENDOR, SDB_DEV_MAC) < 0)
return -1;
ret = sdbfs_fread(&wrc_sdb, 0, mac, 6);
sdbfs_close(&wrc_sdb);
ret =-1;
else
{
ret = sdbfs_fread(&wrc_sdb, 0, mac, 6);
sdbfs_close(&wrc_sdb);
}
if (ret < 0)
pp_printf("%s: SDB error\n", __func__);
......@@ -335,19 +377,20 @@ int get_persistent_mac(uint8_t portnum, uint8_t *mac)
}
if (ret < 0) {
pp_printf("%s: Using W1 serial number\n", __func__);
w1_scan_bus(&wrpc_w1_bus);
for (i = 0; i < W1_MAX_DEVICES; i++) {
class = w1_class(wrpc_w1_bus.devs + i);
if (class != 0x28 && class != 0x42)
continue;
rom = wrpc_w1_bus.devs[i].rom;
mac[0] = 0x22;
mac[1] = 0x33;
mac[2] = rom >> 32;
mac[3] = rom >> 24;
mac[4] = rom >> 16;
mac[5] = rom >> 8;
ret = 0;
}
d = wrpc_w1_bus.devs + i;
if (d->rom) {
mac[0] = 0x22;
mac[1] = 0x33;
mac[2] = 0xff & (d->rom >> 32);
mac[3] = 0xff & (d->rom >> 24);
mac[4] = 0xff & (d->rom >> 16);
mac[5] = 0xff & (d->rom >> 8);
ret = 0;
break;
}
}
}
if (ret < 0) {
pp_printf("%s: failure\n", __func__);
......@@ -392,7 +435,7 @@ int set_persistent_mac(uint8_t portnum, uint8_t *mac)
/* Erase SFB database in the memory */
int32_t storage_sfpdb_erase(void)
int storage_sfpdb_erase(void)
{
int ret;
......@@ -786,7 +829,10 @@ int storage_sdbfs_erase(int mem_type, uint32_t base_adr, uint32_t blocksize,
wrc_sdb.drvdata = &wrpc_w1_bus;
sdb_w1_erase(&wrc_sdb, base_adr, SDBFS_REC *
sizeof(struct sdb_device));
}
} else if (mem_type == MEM_FRAM) {
pp_printf("Erasing FRAM (0x%x)...\n", base_adr);
sdb_fram_erase(NULL, base_adr, SDBFS_REC * blocksize);
}
return 0;
}
......@@ -893,8 +939,14 @@ int storage_gensdbfs(int mem_type, uint32_t base_adr, uint32_t blocksize,
sdb_w1_write(&wrc_sdb, base_adr + i*size, &sdbfs[i],
size);
}
}
} else if (mem_type == MEM_FRAM) {
pp_printf("Formatting SDBFS in FRAM(0x%x)...\n", base_adr);
sdb_fram_erase(NULL, base_adr, SDBFS_REC * size);
for (i = 0; i < SDBFS_REC; ++i) {
sdb_fram_write(NULL, base_adr + i*size, &sdbfs[i],
size);
}
}
/* re-initialize storage after writing sdbfs image */
storage_init(WRPC_FMC_I2C, FMC_EEPROM_ADR);
......
......@@ -43,10 +43,20 @@ various information about Ethernet frame's structure and type:
it will be assigned from WRPC configuration)
\item[] \emph{vCRC} - the frame contains a valid CRC checksum
\item[] \emph{packet class} - the packet class assigned by the classifier
inside WRPC MAC module
inside WRPC MAC module.
\end{itemize}
OOB data is used for passing the timestamp-related information for the incoming and
The packet class assigned by the classifier is one-hot encoded with 8 possible
values: \textit{0x01} for class 0 to \textit{0x80} for class 7. In its default
configuration WRPC assigns {\bf class 0} (\textit{0x01}) to all frames that shall be
processed inside the core (those are never exposed to the user through the
fabric interface); {\bf class 7} (\textit{0x80} to all Etherbone frames that are
either broadcast or unicast with matching destination MAC address; {\bf class 6}
(\textit{0x40}) to all other traffic not qualified to any of the previous
classes.\\
{\bf OOB data} is used for passing the timestamp-related information for the incoming and
outgoing Ethernet frames. Each frame received from a physical link is
timestamped inside the WRPC and this value is passed as Rx OOB
data. On the other hand, for each transmitted frame the Tx timestamp can be read
......
......@@ -42,7 +42,11 @@ type with three possible values:
\item[PLAIN:] No additional module is instantiated and the ``raw'' WRPC fabric interface (see also
Section~\ref{sec:wrpc_fabric}) is provided on the board's ports.
\item[STREAMERS:] A set of \href{http://www.ohwr.org/projects/wr-cores/wiki/WR_Streamers}{TX/RX
streamers} is attached to the WRPC fabric interface.
streamers} is attached to the WRPC fabric interface.\\
\textbf{Note:} The STREAMERS interface can be synchronous to either \textit{clk\_sys\_62m5}
or \textit{clk\_ref\_125m}. By default it is synchronous to \textit{clk\_sys\_62m5}. Generic
can be used to provide data in the \textit{clk\_ref\_125m} clock domain (this is useful for
fixed-latency data transmission).
\item[ETHERBONE:] An \href{http://www.ohwr.org/projects/etherbone-core/wiki}{Etherbone} slave node
is attached to the WRPC fabric interface.
\end{description}
......@@ -173,7 +177,8 @@ their own BSP, can find the board-common module under:
\hline
\hdltablesection{WR streamers (when \tts{g\_fabric\_iface = streamers})}\\
\hline
wrs\_tx\_data\_i & in & var & Data to be sent. Size is equal to \tts{g\_tx\_streamer\_width}\\
wrs\_tx\_data\_i & in & var & Data to be sent. Size and clock domain
configurable via \tts{g\_tx\_streamer\_params}, \textit{clk\_sys\_62m5} by dafault. \\
\hline
wrs\_tx\_valid\_i & in & 1 & Indicates whether \tts{wrs\_tx\_data\_i} contains valid data\\
\hline
......@@ -197,7 +202,8 @@ their own BSP, can find the board-common module under:
\hline
wrs\_rx\_last\_o & out & 1 & Indicates the last word of the data block on \tts{wrs\_rx\_data\_o}\\
\hline
wrs\_rx\_data\_o & out & var & Received data. Size is equal to \tts{g\_rx\_streamer\_width}\\
wrs\_rx\_data\_o & out & var & Received data. Size and clock domain
configurable via \tts{g\_rx\_streamer\_params}, \textit{clk\_sys\_62m5} by dafault.\\
\hline
wrs\_rx\_valid\_o & out & 1 & Indicates that \tts{wrs\_rx\_data\_o} contains valid data\\
\hline
......
This diff is collapsed.
......@@ -433,13 +433,18 @@ you would have to install it manually. E.g. in Ubuntu, please install
First, you need to download and unpack the LM32 toolchain from the location
mentioned in section \ref{Repositories and Releases}. The following example
uses 32bit version of a toolchain. If you encounter problems running it, please
use 64bit version.
uses 32bit version of a toolchain.
\begin{lstlisting}
$ wget http://www.ohwr.org/attachments/download/1133/lm32.tar.xz
$ wget https://www.ohwr.org/project/wrpc-sw/uploads/a2e8eeba448fbc8d580e68004e6f6c7f/lm32.tar.xz
$ tar xJf lm32.tar.xz -C <your_location>
\end{lstlisting}
If you encounter problems running it, please use the 64bit version.
\begin{lstlisting}
$ wget https://www.ohwr.org/project/wrpc-sw/uploads/2776ce0ba43503d1486ae205b48fb450/lm32_host_64bit.tar.xz
$ tar xJf lm32_host_64bit.tar.xz -C <your_location>
\end{lstlisting}
Then you need to set a \texttt{CROSS\_COMPILE} environment variable in order
to compile the software for the LM32 processor:
\begin{lstlisting}
......@@ -531,7 +536,8 @@ $ make
You have to download also the "golden" firmware for SPEC card. It is used by
the drivers to recognize the hardware:
\begin{lstlisting}
$ wget http://www.ohwr.org/attachments/download/4057/spec-init.bin-2015-09-18
$ wget https://www.ohwr.org/project/spec-sw/uploads/636e7eaa2e1c3a884e2f9f694fdfd1b9/spec-init.bin-2015-09-18
$ sudo mv spec-init.bin-2015-09-18 /lib/firmware/fmc/spec-init.bin
\end{lstlisting}
......@@ -1342,24 +1348,26 @@ All the available commands are listed with \texttt{h}:
\begin{lstlisting}[basicstyle=\scriptsize\ttfamily]
cfv-774-cbt:wrstm[00] > h
Valid COMMANDS:
Idx Name Params Description
# 1: q [ ] -> Quit test program
# 2: h [ o c ] -> Help on commands
# 3: a [ ] -> Atom list commands
# 4: his [ ] -> History
# 5: s [ Seconds ] -> Sleep seconds
# 6: ms [ MilliSecs ] -> Sleep milliseconds
# 7: sh [ Unix Cmd ] -> Shell command
# 8: stats [ [0/1/2/3/4/5/6/7] ] -> show streamers statistics
# 9: reset [ ] -> show time of the latest reset / time elapsed since then
#10: resetcnt [ ] -> reset tx/rx/lost counters and avg/min/max latency values
#11: resetseqid [ ] -> reset sequence ID of the tx streamer
#12: lat [ [latency] ] -> get/set config of fixed latency in integer [us] (-1 to disable)
#13: qtagf [ [0/1] ] -> QTags flag on off
#14: qtagvp [ [VID,prio] ] -> QTags Get/Set VLAN ID and priority
#15: qtagor [ [0/1] ] -> get/set overriding of default qtag config with WB config (set
using qtagf, qtagvp)
#16: ls [ [leapseconds] ] -> get/set leap seconds
Idx Name Params Description
# 1: q [ ] -> Quit test program
# 2: h [ o c ] -> Help on commands
# 3: a [ ] -> Atom list commands
# 4: his [ ] -> History
# 5: s [ Seconds ] -> Sleep seconds
# 6: ms [ MilliSecs ] -> Sleep milliseconds
# 7: sh [ Unix Cmd ] -> Shell command
# 8: stats [ [0/1/2/3/4/5/6/7] ] -> show streamers statistics
# 9: reset [ ] -> show time of the latest reset / time elapsed since then
#10: resetcnt [ ] -> reset tx/rx/lost counters and avg/min/max latency values
#11: resetseqid [ ] -> reset sequence ID of the tx streamer
#12: flat [ [fixed latency value] ] -> get/set config of fixed latency in integer [us] (-1 to disable)
#13: flatstats [ ] -> get statistics regarding fixed latency operation
#14: flattimeout [ [timeout value] ] -> get/set fixed latency timeout [us] (-1 to set default: ~1ms)
#15: qtagf [ [0/1] ] -> QTags flag on off
#16: qtagvp [ [VID,prio] ] -> QTags Get/Set VLAN ID and priority
#17: qtagor [ [0/1] ] -> get/set overriding of default qtag config with WB config (set ...
#18: ls [ [leapseconds] ] -> get/set leap seconds
#19: hdlswreset [ ] -> HD software reset of rx and tx streamer HDL modules (excludes ...
Type "h name" to get complete command help
\end{lstlisting}
......@@ -1367,8 +1375,9 @@ In order to see all the WR Streamers statistics, the \texttt{stats} command
inside the prompt should be executed as follows:
\begin{lstlisting}
cfc-774-cbt:wrstm[01] > stats
Latency [us] : min= 3.736 max= 8.216 avg = 3.88176
Frames [number]: tx =0 rx =61897834620 lost=0 (lost blocks =0)
Latency [us] : min= 3.824 max= 5.656 avg = 3.8958 (overflow =0)
Frames [number]: tx = 1558137 rx = 1558137 lost= 0 (lost blocks =0)
\end{lstlisting}
The commands that are available from the interactive prompt can be also executed directly
......@@ -2041,7 +2050,7 @@ package.
First, please download the SDBFS image from \textit{ohwr.org}:
\begin{lstlisting}
$ wget http://www.ohwr.org/attachments/download/4060/sdbfs-flash.bin
$ wget https://www.ohwr.org/project/wr-cores/uploads/6f33b5a8660bd0f2ff7a07526b4484d6/sdbfs-flash.bin
\end{lstlisting}
It contains all the files required by the core. They are empty, but have to
exist in the SDBFS structure to be filled later from the WR PTP Core shell or
......@@ -2080,7 +2089,7 @@ This \textit{mcs} file already includes both SDBFS image and FPGA bitstream.
In the case when you want to run a custom gateware or you have a custom hardware, you can
download a standalone SDBFS image:
\begin{lstlisting}
$ wget http://www.ohwr.org/attachments/download/4558/sdbfs-standalone-160812.bin
$ wget https://www.ohwr.org/project/wr-cores/uploads/9dad995e74a3d49b472b8654833be01a/sdbfs-standalone-160812.bin
\end{lstlisting}
and generate a custom \textit{*.mcs} file with your own FPGA bitstream. You should
use the following layout:
......
......@@ -20,9 +20,11 @@
/* WR Reference clock period (picoseconds) and frequency (Hz) */
#ifdef CONFIG_WR_NODE_PCS16
# define NS_PER_CLOCK 16
# define REF_CLOCK_PERIOD_PS 16000
# define REF_CLOCK_FREQ_HZ 62500000
#else
# define NS_PER_CLOCK 8
# define REF_CLOCK_PERIOD_PS 8000
# define REF_CLOCK_FREQ_HZ 125000000
#endif
......
......@@ -10,6 +10,7 @@
#define CPU_CLOCK 62500000
#define REF_CLOCK_FREQ_HZ 62500000
#define NS_PER_CLOCK 16
#define REF_CLOCK_PERIOD_PS 16000
#define UART_BAUDRATE 115200
......@@ -21,6 +22,7 @@
#define BASE_GPIO 0x10300
#define BASE_TIMER 0x10400
#define BASE_PPS_GEN 0x10500
#define BASE_SPI_LJD_BOARD 0x10700
/* spll parameter that are board-specific */
#define BOARD_DIVIDE_DMTD_CLOCKS 0
......
......@@ -13,6 +13,10 @@
#define FLASH_BLOCKSIZE 65536
void delay(void);
uint8_t bbspi_transfer(int cspin, uint8_t val);
void flash_init(void);
/* Flash interface functions */
void flash_init(void);
int flash_write(uint32_t addr, uint8_t *buf, int count);
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#ifndef __FRAM_H_
#define __FRAM_H_
#include "types.h"
/* Fram interface functions */
void fram_init(void);
int fram_write(uint32_t addr, uint8_t *buf, int count);
int fram_read(uint32_t addr, uint8_t *buf, int count);
int fram_erase(uint32_t addr, int count);
/* SDB flash interface functions */
int fram_sdb_check(void);
#endif // __FRAM_H_
......@@ -10,6 +10,13 @@
#include "board.h"
#define GPIO_SYS_CLK_SEL 0
#define GPIO_PLL_RESET_N 1
#define GPIO_PERIPH_RESET_N 3
#define GPIO_LJD_BOARD_DETECT 4
extern int ljd_present;
struct GPIO_WB
{
uint32_t CODR; /*Clear output register*/
......@@ -36,7 +43,7 @@ static inline void gpio_dir(int pin, int val)
__gpio->DDR &= ~(1<<pin);
}
static inline int gpio_in(int bank, int pin)
static inline int gpio_in(int pin)
{
return __gpio->PSR & (1<<pin) ? 1: 0;
}
......
......@@ -3,8 +3,8 @@
* File : ./doc/wr_streamers.h
* Author : auto-generated by wbgen2 from wr_streamers_wb.wb
* Created : Tue Jun 20 08:53:54 2017
* Version : 0x00000001
* Created : Thu May 23 16:11:14 2019
* Version : 0x00000002
* Standard : ANSI C
THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wr_streamers_wb.wb
......@@ -36,7 +36,7 @@
#endif
/* version definition */
#define WBGEN2_WR_STREAMERS_VERSION 0x00000001
#define WBGEN2_WR_STREAMERS_VERSION 0x00000002
/* definitions for register: Version register */
......@@ -359,6 +359,67 @@
#define WR_STREAMERS_DUMMY_DUMMY_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_DUMMY_DUMMY_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Reset Register */
/* definitions for field: Software reset streamers in reg: Reset Register */
#define WR_STREAMERS_RSTR_RST_SW WBGEN2_GEN_MASK(0, 1)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX Late Frames Count (LSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB_SHIFT 0
#define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT15_RX_LATE_FRAMES_CNT_LSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX Late Frames Count (MSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB_SHIFT 0
#define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT16_RX_LATE_FRAMES_CNT_MSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX Timed-out Frames Count (LSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB_SHIFT 0
#define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT17_RX_TIMEOUT_FRAMES_CNT_LSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX Timed-out Frames Count (MSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB_SHIFT 0
#define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT18_RX_TIMEOUT_FRAMES_CNT_MSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX OK Frames Count (LSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB_SHIFT 0
#define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT19_RX_MATCH_FRAMES_CNT_LSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx statistics */
/* definitions for field: WR Streamer RX OK Frames Count (MSB) in reg: Rx statistics */
#define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB_MASK WBGEN2_GEN_MASK(0, 32)
#define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB_SHIFT 0
#define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB_W(value) WBGEN2_GEN_WRITE(value, 0, 32)
#define WR_STREAMERS_RX_STAT20_RX_MATCH_FRAMES_CNT_MSB_R(reg) WBGEN2_GEN_READ(reg, 0, 32)
/* definitions for register: Rx Config Reg 6 */
/* definitions for field: RX Fixed Latency Timeout (Default: 0x1000000=~134ms) in reg: Rx Config Reg 6 */
#define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_MASK WBGEN2_GEN_MASK(0, 28)
#define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_SHIFT 0
#define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_W(value) WBGEN2_GEN_WRITE(value, 0, 28)
#define WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_R(reg) WBGEN2_GEN_READ(reg, 0, 28)
PACKED struct WR_STREAMERS_WB {
/* [0x0]: REG Version register */
uint32_t VER;
......@@ -428,6 +489,22 @@ PACKED struct WR_STREAMERS_WB {
uint32_t DBG_DATA;
/* [0x84]: REG Test value */
uint32_t DUMMY;
/* [0x88]: REG Reset Register */
uint32_t RSTR;
/* [0x8c]: REG Rx statistics */
uint32_t RX_STAT15;
/* [0x90]: REG Rx statistics */
uint32_t RX_STAT16;
/* [0x94]: REG Rx statistics */
uint32_t RX_STAT17;
/* [0x98]: REG Rx statistics */
uint32_t RX_STAT18;
/* [0x9c]: REG Rx statistics */
uint32_t RX_STAT19;
/* [0xa0]: REG Rx statistics */
uint32_t RX_STAT20;
/* [0xa4]: REG Rx Config Reg 6 */
uint32_t RX_CFG6;
};
#endif
......@@ -3,15 +3,24 @@
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#ifndef _UINT32_T_DECLARED
typedef unsigned int uint32_t;
#define _UINT32_T_DECLARED
#endif
typedef unsigned long long uint64_t;
typedef signed char int8_t;
typedef signed short int16_t;
#ifndef _INT32_T_DECLARED
typedef signed int int32_t;
#define _INT32_T_DECLARED
#endif
typedef signed long long int64_t;
#ifndef _INTPTR_T_DECLARED
typedef unsigned long intptr_t;
#define _INTPTR_T_DECLARED
#endif
#define UINT32_MAX 4294967295U
......
......@@ -88,6 +88,7 @@ extern struct storage_config storage_cfg;
#define MEM_FLASH 0
#define MEM_EEPROM 1
#define MEM_1W_EEPROM 2
#define MEM_FRAM 3
#define SDBFS_REC 5
int storage_read_hdl_cfg(void);
......
......@@ -53,13 +53,6 @@ extern int wrc_vlan_number;
int wrc_mon_gui(void);
void shell_init(void);
/* This header is included by softpll: manage wrc/wrs difference */
#ifdef CONFIG_WR_NODE
#define NS_PER_CLOCK 8
#else /* CONFIG_WR_SWITCH */
#define NS_PER_CLOCK 16
#endif
/* Default width (in 8ns/16ns units) of the pulses on the PPS output */
#define PPS_WIDTH (10 * 1000 * 1000 / NS_PER_CLOCK) /* 10ms */
......@@ -70,7 +63,8 @@ extern int abs(int val);
extern int wrc_ui_refperiod;
/* Init functions and defaults for the wrs build */
int ad9516_init(int scb_ver);
int ad9516_init(int scb_ver, int ljd_present);
int ljd_ad9516_init(void);
void rts_init(void);
int rtipc_init(void);
void rts_update(void);
......
......@@ -204,6 +204,16 @@ static int rts_enable_ptracker_func(const struct minipc_pd *pd, uint32_t *args,
return 0;
}
static int rts_set_average_samples_func(const struct minipc_pd *pd, uint32_t *args, void *ret)
{
pstate.ipc_count++;
spll_set_ptracker_average_samples((int)args[0], (int)args[1]);
*(int *) ret = 0;
return 0;
}
static int rts_debug_command_func(const struct minipc_pd *pd, uint32_t *args, void *ret)
{
pstate.ipc_count++;
......@@ -228,6 +238,7 @@ int rtipc_init(void)
rtipc_rts_adjust_phase_struct.f = rts_adjust_phase_func;
rtipc_rts_enable_ptracker_struct.f = rts_enable_ptracker_func;
rtipc_rts_debug_command_struct.f = rts_debug_command_func;
rtipc_rts_set_average_samples_struct.f = rts_set_average_samples_func;
minipc_export(server, &rtipc_rts_set_mode_struct);
minipc_export(server, &rtipc_rts_get_state_struct);
......@@ -235,6 +246,7 @@ int rtipc_init(void)
minipc_export(server, &rtipc_rts_adjust_phase_struct);
minipc_export(server, &rtipc_rts_enable_ptracker_struct);
minipc_export(server, &rtipc_rts_debug_command_struct);
minipc_export(server, &rtipc_rts_set_average_samples_struct);
return 0;
......
......@@ -187,6 +187,16 @@ static struct minipc_pd rtipc_rts_debug_command_struct = {
},
};
static struct minipc_pd rtipc_rts_set_average_samples_struct = {
.name = "gggg",
.retval = MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int),
.args = {
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int ),
MINIPC_ARG_ENCODE(MINIPC_ATYPE_INT, int ),
MINIPC_ARG_END
},
};
#endif
#endif
......@@ -742,6 +742,94 @@ wrpcSfpAlpha OBJECT-TYPE
::= { wrpcSfpEntry 5 }
-- ****************************************************************************
wrpcInitScriptConfigGroup OBJECT IDENTIFIER ::= { wrpcCore 9 }
wrpcInitScriptConfigApply OBJECT-TYPE
SYNTAX INTEGER {
na(0),
writeToFlash(1),
eraseFlash(50),
applySuccessful(100),
applyFailed(200),
applyFailedEmptyLine(201)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Make a change to a init script
writeToFlash - Add a defined command from wrpcInitScriptConfigLine to the init script
eraseFlash - Erase init script in the flash.
applySuccessful - Configuration applied successfully.
applyFailed - Failed to update init script.
applyFailedEmptyLine - Failed to update init script because wrpcInitScriptConfigLine is empty.
"
::= { wrpcInitScriptConfigGroup 1 }
wrpcInitScriptConfigLine OBJECT-TYPE
SYNTAX DisplayString (SIZE(0..31))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Line to be added to the init script."
::= { wrpcInitScriptConfigGroup 2 }
-- ****************************************************************************
wrpcSdbGroup OBJECT IDENTIFIER ::= { wrpcCore 10 }
wrpcSdbApply OBJECT-TYPE
SYNTAX INTEGER {
na(0),
writeToFlash(1),
eraseFlash(50),
applySuccessful(100),
applyFailed(200),
applyFailedEmptyParam(201)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Make a change to a sdbfs
writeToFlash - Generate sdb in flash; requires other OIDs in this group to be set first.
eraseFlash - Erase flash; requires other OIDs in this group to be set first.
applySuccessful - Configuration applied successfully.
applyFailed - Failed to update flash.
applyFailedEmptyParam - Failed to update flash, some params are empty.
"
::= { wrpcSdbGroup 1 }
wrpcSdbMemType OBJECT-TYPE
SYNTAX INTEGER {
flash(0),
eeprom(1),
w1eeprom(2),
fram(3)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Memory type"
::= { wrpcSdbGroup 2 }
wrpcSdbBaseAddr OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Base address"
::= { wrpcSdbGroup 3 }
wrpcSdbParam OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"The meaning of this OID depends on the type of selected storage.
It is either the sector size in kilobytes (for Flash) or I2C chip
address (for I2C EEPROM)."
::= { wrpcSdbGroup 4 }
-- ****************************************************************************
END
......@@ -122,6 +122,15 @@
#define applyFailedDBFull 202
#define applyFailedInvalidPN 203
/* new defines for wrpcInitScriptConfigApply, some are used from
* wrpcPtpConfigApply */
#define writeToFlash 1
#define applyFailedEmptyLine 201
/* new defines for oid_wrpcSdbApply, some are used from
* wrpcPtpConfigApply */
#define applyFailedEmptyParam 201
/* defines for wrpcTemperatureTable */
#define TABLE_ROW 1
#define TABLE_COL 0
......@@ -213,6 +222,15 @@ struct snmp_oid_limb {
static struct s_sfpinfo snmp_ptp_config;
static int ptp_config_apply_status;
static int ptp_restart_status;
static char init_script_line[32];
static int init_script_config_apply_status;
/* related to wrpcSdbGroup */
static int sdb_apply_status;
static int sdb_mem_type = -1;
static int sdb_base_addr = -1;
static int sdb_param = -1;
/* Keep the number of aux diag registers available in the FPGA bitstream */
static uint32_t aux_diag_reg_ro_num;
static uint32_t aux_diag_reg_rw_num;
......@@ -260,6 +278,8 @@ static int set_pp(uint8_t *buf, struct snmp_oid *obj);
static int set_p(uint8_t *buf, struct snmp_oid *obj);
static int set_ptp_restart(uint8_t *buf, struct snmp_oid *obj);
static int set_ptp_config(uint8_t *buf, struct snmp_oid *obj);
static int set_init_script_config(uint8_t *buf, struct snmp_oid *obj);
static int set_sdb(uint8_t *buf, struct snmp_oid *obj);
static int set_aux_diag(uint8_t *buf, struct snmp_oid *obj);
static int data_aux_diag(uint8_t *buf, struct snmp_oid *obj, int mode);
......@@ -276,6 +296,8 @@ static uint8_t oid_wrpcPtpConfigGroup[] = {0x2B,6,1,4,1,96,101,1,6};
static uint8_t oid_wrpcPortGroup[] = {0x2B,6,1,4,1,96,101,1,7};
/* Include wrpcSfpEntry into OID */
static uint8_t oid_wrpcSfpTable[] = {0x2B,6,1,4,1,96,101,1,8,1};
static uint8_t oid_wrpcInitScriptConfigGroup[] = {0x2B,6,1,4,1,96,101,1,9};
static uint8_t oid_wrpcSdbGroup[] = {0x2B,6,1,4,1,96,101,1,10};
/* In below OIDs zeros will be replaced in the snmp_init function by values
* read from FPA */
static uint8_t oid_wrpcAuxRoTable[] = {0x2B,6,1,4,1,96,101,2,0,0,1,1};
......@@ -347,6 +369,17 @@ static uint8_t oid_wrpcSfpDeltaTx[] = {3};
static uint8_t oid_wrpcSfpDeltaRx[] = {4};
static uint8_t oid_wrpcSfpAlpha[] = {5};
/* wrpcInitScriptConfigGroup */
static uint8_t oid_wrpcInitScriptConfigApply[] = {1,0};
static uint8_t oid_wrpcInitScriptConfigLine[] = {2,0};
/* oid_wrpcSdbGroup */
static uint8_t oid_wrpcSdbApply[] = {1,0};
static uint8_t oid_wrpcSdbMemType[] = {2,0};
static uint8_t oid_wrpcSdbBaseAddr[] = {3,0};
static uint8_t oid_wrpcSdbParam[] = {4,0};
/* NOTE: to have SNMP_GET_NEXT working properly this array has to be sorted by
OIDs */
/* wrpcVersionGroup */
......@@ -440,6 +473,22 @@ static struct snmp_oid oid_array_wrpcSfpTable[] = {
{ 0, }
};
/* wrpcInitScriptConfigGroup */
static struct snmp_oid oid_array_wrpcInitScriptConfigGroup[] = {
OID_FIELD_VAR( oid_wrpcInitScriptConfigApply, get_p, set_init_script_config, ASN_INTEGER, &init_script_config_apply_status),
OID_FIELD_VAR( oid_wrpcInitScriptConfigLine, get_p, set_p, ASN_OCTET_STR, &init_script_line),
{ 0, }
};
/* wrpcSdbGroup */
static struct snmp_oid oid_array_wrpcSdbGroup[] = {
OID_FIELD_VAR( oid_wrpcSdbApply, get_p, set_sdb, ASN_INTEGER, &sdb_apply_status),
OID_FIELD_VAR( oid_wrpcSdbMemType, get_p, set_p, ASN_INTEGER, &sdb_mem_type),
OID_FIELD_VAR( oid_wrpcSdbBaseAddr, get_p, set_p, ASN_INTEGER, &sdb_base_addr),
OID_FIELD_VAR( oid_wrpcSdbParam, get_p, set_p, ASN_INTEGER, &sdb_param),
{ 0, }
};
static struct snmp_oid oid_array_wrpcAuxRoTable[] = {
OID_FIELD_VAR(NULL, get_aux_diag, NO_SET, ASN_UNSIGNED, AUX_DIAG_RO),
{ 0, }
......@@ -461,6 +510,12 @@ static struct snmp_oid_limb oid_limb_array[] = {
OID_LIMB_FIELD(oid_wrpcPtpConfigGroup, func_group, oid_array_wrpcPtpConfigGroup),
OID_LIMB_FIELD(oid_wrpcPortGroup, func_group, oid_array_wrpcPortGroup),
OID_LIMB_FIELD(oid_wrpcSfpTable, func_table, oid_array_wrpcSfpTable),
#ifdef CONFIG_SNMP_INIT
OID_LIMB_FIELD(oid_wrpcInitScriptConfigGroup, func_group, oid_array_wrpcInitScriptConfigGroup),
#endif
#ifdef CONFIG_SNMP_SDB
OID_LIMB_FIELD(oid_wrpcSdbGroup, func_group, oid_array_wrpcSdbGroup),
#endif
#ifdef CONFIG_SNMP_AUX_DIAG
OID_LIMB_FIELD(oid_wrpcAuxRoTable, func_aux_diag, oid_array_wrpcAuxRoTable),
OID_LIMB_FIELD(oid_wrpcAuxRwTable, func_aux_diag, oid_array_wrpcAuxRwTable),
......@@ -1335,6 +1390,112 @@ static int set_ptp_config(uint8_t *buf, struct snmp_oid *obj)
return ret;
}
static int set_init_script_config(uint8_t *buf, struct snmp_oid *obj)
{
int ret;
int32_t *apply_mode;
char *args[3];
char arg2='\0'; /* end list of args */
apply_mode = obj->p;
ret = set_value(buf, obj, apply_mode);
if (ret <= 0)
return ret;
switch (*apply_mode) {
case writeToFlash:
if (init_script_line[0] == '\0') {
*apply_mode = applyFailedEmptyLine;
pp_printf("SNMP: empty init line\n");
break;
}
/* pass a list of args, the args[0] is ignored by
* storage_init_add, so we don't care */
args[1] = init_script_line;
args[2] = &arg2;
if (storage_init_add((const char **)args) < 0)
*apply_mode = applyFailed;
else
*apply_mode = applySuccessful;
break;
case eraseFlash:
if (storage_init_erase() < 0)
*apply_mode = applyFailed;
else
*apply_mode = applySuccessful;
break;
default:
*apply_mode = applyFailed;
}
snmp_verbose("%s: init_script_line: %s\n", __func__,
init_script_line);
return ret;
}
static int set_sdb(uint8_t *buf, struct snmp_oid *obj)
{
int ret;
int32_t *apply_mode;
uint8_t i2c_adr = FMC_EEPROM_ADR;
int blocksize = 1;
apply_mode = obj->p;
ret = set_value(buf, obj, apply_mode);
if (ret <= 0)
return ret;
snmp_verbose("%s enter\n", __func__);
if (sdb_mem_type == -1
|| sdb_base_addr == -1
|| sdb_param == -1) {
*apply_mode = applyFailedEmptyParam;
pp_printf("%s wrong params\n", __func__);
return ret;
}
if (sdb_mem_type == MEM_FLASH)
blocksize = sdb_param * 1024;
else if (sdb_param)
i2c_adr = sdb_param;
switch (*apply_mode) {
case writeToFlash:
snmp_verbose("%s writeToFlash\n", __func__);
if (storage_gensdbfs(sdb_mem_type, sdb_base_addr, blocksize,
i2c_adr) < 0)
*apply_mode = applyFailed;
else
*apply_mode = applySuccessful;
break;
case eraseFlash:
snmp_verbose("%s eraseFlash\n", __func__);
if (storage_sdbfs_erase(sdb_mem_type, sdb_base_addr, blocksize,
i2c_adr) < 0)
*apply_mode = applyFailed;
else
*apply_mode = applySuccessful;
break;
default:
*apply_mode = applyFailed;
}
if (*apply_mode == applySuccessful) {
/* If apply was successful, clear sdb params */
sdb_mem_type = -1;
sdb_base_addr = -1;
sdb_param = -1;
}
return ret;
}
/*
* Perverse... snmpwalk does getnext anyways.
*
......@@ -1498,14 +1659,19 @@ static int snmp_respond(uint8_t *buf)
* functions below when SNMP compiled without SET support.
* These functions will never be called here. */
if (0) {
set_p(NULL, NULL);
set_pp(NULL, NULL);
set_ptp_config(NULL, NULL);
set_ptp_restart(NULL, NULL);
set_aux_diag(NULL, NULL);
func_aux_diag(NULL, 0, NULL, 0);
(void) set_init_script_config;
(void) set_p;
(void) set_pp;
(void) set_ptp_config;
(void) set_ptp_restart;
(void) set_aux_diag;
(void) func_aux_diag(NULL, 0, NULL, 0);
oid_array_wrpcAuxRwTable[0].oid_len = 0;
oid_array_wrpcAuxRoTable[0].oid_len = 0;
oid_array_wrpcInitScriptConfigGroup[0].oid_len = 0;
(void) oid_wrpcInitScriptConfigGroup;
oid_array_wrpcSdbGroup[0].oid_len = 0;
(void) oid_wrpcSdbGroup;
}
for (a_i = 0, h_i = 0; a_i < sizeof(match_array); a_i++, h_i++) {
......
......@@ -10,6 +10,7 @@ LOBJ := devmap.o
GIT_VER ?= $(shell git describe --always --dirty)
GIT_USR ?= $(shell git config --get-all user.name)
CC = cc
CFLAGS = -Wall -ggdb -fPIC -Werror -I./ -I../include
CFLAGS += -D__GIT_VER__="\"$(GIT_VER)\"" -D__GIT_USR__="\"$(GIT_USR)\""
LDFLAGS = -L.
......
......@@ -9,6 +9,7 @@ GIT_USR =? $(shell git config --get-all user.name)
LIB = libextest.a
LOBJ := extest.o
CC = cc
CFLAGS = -Wall -ggdb -fPIC -Werror -I./
CFLAGS += -D__GIT_VER__="\"$(GIT_VER)\"" -D__GIT_USR__="\"$(GIT_USR)\""
LDFLAGS = -L. -lextest
......
......@@ -330,6 +330,11 @@ static int wrc_log_stats(void)
ptp_mode != WRC_MODE_SLAVE)
return 0;
last_jiffies = timer_get_tics();
/* Print only one time */
if(wrc_stat_running == -1)
wrc_stat_running = 0;
wrc_stats_last = s->update_count;
shw_pps_gen_get_time(&sec, &nsec);
......
......@@ -10,6 +10,7 @@
#include "syscon.h"
#include "hw/memlayout.h"
#include "storage.h"
#include <flash.h>
/*
* args[1] - where to write sdbfs image (0 - Flash, 1 - I2C EEPROM,
......@@ -33,6 +34,8 @@ static int cmd_sdb(const char *args[])
/* interpret args[3] as i2c adr or blocksize depending on memory type */
if (args[3] && atoi(args[1]) == MEM_FLASH)
blocksize = atoi(args[3])*1024;
else if (args[3] && atoi(args[1]) == MEM_FRAM)
blocksize = atoi(args[3]);
else if (args[3])
i2c_adr = atoi(args[3]);
......@@ -45,10 +48,11 @@ static int cmd_sdb(const char *args[])
return 0;
}
if (!strcasecmp(args[0], "fs") && storage_cfg.valid &&
atoi(args[1]) == MEM_FLASH) {
(atoi(args[1]) == MEM_FLASH ||
atoi(args[1]) == MEM_FRAM)) {
/* if available, we can also use Flash parameters specified with
* HDL generics */
storage_gensdbfs(MEM_FLASH, storage_cfg.baseadr,
storage_gensdbfs(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0);
return 0;
}
......@@ -59,12 +63,12 @@ static int cmd_sdb(const char *args[])
return 0;
}
if (!strcasecmp(args[0], "fse") && storage_cfg.valid &&
atoi(args[1]) == MEM_FLASH) {
storage_sdbfs_erase(MEM_FLASH, storage_cfg.baseadr,
(atoi(args[1]) == MEM_FLASH ||
atoi(args[1]) == MEM_FRAM)) {
storage_sdbfs_erase(atoi(args[1]), storage_cfg.baseadr,
storage_cfg.blocksize, 0);
return 0;
}
return -EINVAL;
}
......
......@@ -35,6 +35,9 @@ static int cmd_stat(const char *args[])
} else if (!strcasecmp(args[0], "off")) {
wrc_stat_running = 0;
pp_printf("statistics now off\n");
} else if (!strcasecmp(args[0], "1")) {
wrc_stat_running = -1; /* Special meaning... (only one) */
wrc_stats_last--; /* force a line to be printed */
} else
return -EINVAL;
return 0;
......
......@@ -32,7 +32,7 @@ volatile struct SPLL_WB *SPLL;
volatile struct PPSG_WB *PPSG;
int spll_n_chan_ref, spll_n_chan_out;
int ljd_present = 0; /* Low-jitter Daughterboard presence indicator */
#define MAIN_CHANNEL (spll_n_chan_ref)
......@@ -283,6 +283,7 @@ void _irq_entry(void)
void spll_very_init()
{
PPSG = (volatile struct PPSG_WB *)BASE_PPS_GEN;
PPSG->ESCR = 0;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_CNT_RST | PPSG_CR_PWIDTH_W(PPS_WIDTH);
}
......@@ -317,8 +318,7 @@ void spll_init(int mode, int slave_ref_channel, int align_pps)
SPLL->OCCR = 0;
SPLL->DEGLITCH_THR = 1000;
PPSG->ESCR = 0;
PPSG->CR = PPSG_CR_CNT_EN | PPSG_CR_PWIDTH_W(PPS_WIDTH);
PPSG->CR |= PPSG_CR_CNT_EN;
if(mode == SPLL_MODE_DISABLED)
s->seq_state = SEQ_DISABLED;
......@@ -467,6 +467,21 @@ int spll_read_ptracker(int channel, int32_t *phase_ps, int *enabled)
return st->ready;
}
void spll_set_ptracker_average_samples(int channel, int nsamples)
{
struct softpll_state *s = (struct softpll_state *) &softpll;
struct spll_ptracker_state *pt = &s->ptrackers[channel];
disable_irq();
pt->preserve_sign = 0;
pt->ready = 0;
pt->acc = 0;
pt->avg_count = 0;
pt->n_avg = nsamples;
enable_irq();
}
void spll_get_num_channels(int *n_ref, int *n_out)
{
if (n_ref)
......@@ -485,12 +500,12 @@ void spll_show_stats()
if (softpll.mode > 0)
pp_printf("softpll: irqs %d seq %s mode %d "
"alignment_state %d HL%d ML%d HY=%d MY=%d DelCnt=%d\n",
"alignment_state %d HL%d ML%d HY=%d MY=%d DelCnt=%d setpoint:%d\n",
s->irq_count, statename,
s->mode, s->ext.align_state,
s->helper.ld.locked, s->mpll.ld.locked,
s->helper.pi.y, s->mpll.pi.y,
s->delock_count);
s->delock_count, s->mpll.phase_shift_current);
}
int spll_shifter_busy(int channel)
......@@ -649,7 +664,7 @@ int spll_update()
return ret != 0;
}
static int spll_measure_frequency(int osc)
int spll_measure_frequency(int osc)
{
volatile uint32_t *reg;
......@@ -667,7 +682,7 @@ static int spll_measure_frequency(int osc)
return 0;
}
timer_delay_ms(2000);
// timer_delay_ms(2000);
return (*reg ) & (0xfffffff);
}
......@@ -699,20 +714,20 @@ static int calc_apr(int meas_min, int meas_max, int f_center )
void check_vco_frequencies()
{
disable_irq();
//disable_irq();
int f_min, f_max;
pll_verbose("SoftPLL VCO Frequency/APR test:\n");
spll_set_dac(-1, 0);
// spll_set_dac(-1, 0);
f_min = spll_measure_frequency(SPLL_OSC_DMTD);
spll_set_dac(-1, 65535);
// spll_set_dac(-1, 65535);
f_max = spll_measure_frequency(SPLL_OSC_DMTD);
pll_verbose("DMTD VCO: Low=%d Hz Hi=%d Hz, APR = %d ppm.\n", f_min, f_max, calc_apr(f_min, f_max, 62500000));
spll_set_dac(0, 0);
// spll_set_dac(0, 0);
f_min = spll_measure_frequency(SPLL_OSC_REF);
spll_set_dac(0, 65535);
// spll_set_dac(0, 65535);
f_max = spll_measure_frequency(SPLL_OSC_REF);
pll_verbose("REF VCO: Low=%d Hz Hi=%d Hz, APR = %d ppm.\n", f_min, f_max, calc_apr(f_min, f_max, REF_CLOCK_FREQ_HZ));
......
......@@ -107,6 +107,8 @@ void spll_set_dac(int out_channel, int value);
int spll_get_dac(int out_channel);
void check_vco_frequencies(void);
int spll_measure_frequency(int osc);
void spll_set_ptracker_average_samples(int channel, int nsamples);
/*
* Aux and main state:
......@@ -148,6 +150,7 @@ struct spll_fifo_log {
};
#define FIFO_LOG_LEN 16
extern int ljd_present;
#endif // __SOFTPLL_NG_H
......@@ -14,13 +14,14 @@
#include "softpll_ng.h"
#include "irq.h"
#define ALIGN_SAMPLE_PERIOD 100000
#define ALIGN_TARGET 0
#define EXT_PERIOD_NS 100
#define EXT_FREQ_HZ 10000000
#define EXT_PPS_LATENCY_PS 30000 // fixme: make configurable
// fixme: make configurable
#define EXT_PPS_LATENCY_PS 30000 // for regular ext channel
#define EXT_PPS_LATENCY_LJD_PS 63000 // for low-jitter daughterboard
void external_init(volatile struct spll_external_state *s, int ext_ref,
......@@ -28,6 +29,8 @@ void external_init(volatile struct spll_external_state *s, int ext_ref,
{
int idx = spll_n_chan_ref + spll_n_chan_out;
if (ljd_present)
idx++;
helper_init(s->helper, idx);
mpll_init(s->main, idx, spll_n_chan_ref);
......@@ -38,7 +41,7 @@ void external_init(volatile struct spll_external_state *s, int ext_ref,
void external_start(struct spll_external_state *s)
{
helper_start(s->helper);
helper_start(s->helper);
SPLL->ECCR = SPLL_ECCR_EXT_EN;
......@@ -50,10 +53,10 @@ void external_start(struct spll_external_state *s)
int external_locked(volatile struct spll_external_state *s)
{
if (!s->helper->ld.locked || !s->main->ld.locked ||
!(SPLL->ECCR & SPLL_ECCR_EXT_REF_LOCKED) || // ext PLL became unlocked
(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED)) // 10MHz unplugged (only SPEC)
!(SPLL->ECCR & SPLL_ECCR_EXT_REF_LOCKED) || // ext PLL became unlocked
(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED)) // 10MHz unplugged (only SPEC)
return 0;
switch(s->align_state) {
case ALIGN_STATE_EXT_OFF:
case ALIGN_STATE_WAIT_CLKIN:
......@@ -83,27 +86,53 @@ static int align_sample(int channel, int *v)
return 0; // sample not valid
}
static inline int get_pps_latency(int sel)
{
if (sel)
return EXT_PPS_LATENCY_LJD_PS;
else
return EXT_PPS_LATENCY_PS;
}
int external_align_fsm(volatile struct spll_external_state *s)
{
int v, done_sth = 0;
static int timeout;
switch(s->align_state) {
case ALIGN_STATE_EXT_OFF:
break;
case ALIGN_STATE_WAIT_CLKIN:
if( !(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED) ) {
if(!ljd_present && !(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED) ) {
SPLL->ECCR |= SPLL_ECCR_EXT_REF_PLLRST;
s->align_state = ALIGN_STATE_WAIT_PLOCK;
done_sth++;
}
#if defined(CONFIG_WR_SWITCH)
else if (ljd_present) {
uint32_t f_ext;
int ljd_ad9516_stat;
/* reset ljd ad9516 */
SPLL->ECCR |= SPLL_ECCR_EXT_REF_PLLRST;
timer_delay(10);
SPLL->ECCR &= (~SPLL_ECCR_EXT_REF_PLLRST);
timer_delay(10);
ljd_ad9516_stat = ljd_ad9516_init();
f_ext = spll_measure_frequency(SPLL_OSC_EXT);
if (!ljd_ad9516_stat && (f_ext > 9999000) && (f_ext < 10001000)) {
s->align_state = ALIGN_STATE_WAIT_PLOCK;
pp_printf("External AD9516 locked\n");
}
}
#endif
break;
case ALIGN_STATE_WAIT_PLOCK:
SPLL->ECCR &= (~SPLL_ECCR_EXT_REF_PLLRST);
if( SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED )
if(SPLL->ECCR & SPLL_ECCR_EXT_REF_STOPPED )
s->align_state = ALIGN_STATE_WAIT_CLKIN;
else if( SPLL->ECCR & SPLL_ECCR_EXT_REF_LOCKED )
else if(SPLL->ECCR & SPLL_ECCR_EXT_REF_LOCKED)
s->align_state = ALIGN_STATE_START;
done_sth++;
break;
......@@ -115,6 +144,9 @@ int external_align_fsm(volatile struct spll_external_state *s)
enable_irq();
s->align_state = ALIGN_STATE_START_MAIN;
done_sth++;
} else if (time_after(timer_get_tics(), timeout + 5*TICS_PER_SECOND)) {
pll_verbose("EXT: timeout, restarting\n");
s->align_state = ALIGN_STATE_WAIT_CLKIN;
}
break;
......@@ -127,6 +159,9 @@ int external_align_fsm(volatile struct spll_external_state *s)
s->align_state = ALIGN_STATE_INIT_CSYNC;
pll_verbose("EXT: DMTD locked.\n");
done_sth++;
} else if (time_after(timer_get_tics(), timeout + 5*TICS_PER_SECOND)) {
pll_verbose("EXT: timeout, restarting\n");
s->align_state = ALIGN_STATE_WAIT_CLKIN;
}
break;
......@@ -171,8 +206,8 @@ int external_align_fsm(volatile struct spll_external_state *s)
s->align_shift += s->align_step;
mpll_set_phase_shift(s->main, s->align_shift);
} else if (v == s->align_target) {
s->align_shift += EXT_PPS_LATENCY_PS;
mpll_set_phase_shift(s->main, s->align_shift);
s->align_shift += get_pps_latency(ljd_present);
mpll_set_phase_shift(s->main, s->align_shift);
s->align_state = ALIGN_STATE_COMPENSATE_DELAY;
}
done_sth++;
......@@ -197,5 +232,8 @@ int external_align_fsm(volatile struct spll_external_state *s)
default:
break;
}
if (done_sth > 0) {
timeout = timer_get_tics();
}
return done_sth != 0;
}
......@@ -17,8 +17,13 @@ void helper_init(struct spll_helper_state *s, int ref_channel)
/* Phase branch PI controller */
s->pi.y_min = 5;
s->pi.y_max = (1 << DAC_BITS) - 5;
#if defined(CONFIG_WR_NODE)
s->pi.kp = -150;//(int)(0.3 * 32.0 * 16.0); // / 2;
s->pi.ki = -2;//(int)(0.03 * 32.0 * 3.0); // / 2;
#else
s->pi.kp = 150;
s->pi.ki = 2;
#endif
s->pi.anti_windup = 1;
/* Phase branch lock detection */
......@@ -83,8 +88,11 @@ void helper_start(struct spll_helper_state *s)
{
/* Set the bias to the upper end of tuning range. This is to ensure that
the HPLL will always lock on positive frequency offset. */
#if defined(CONFIG_WR_SWITCH)
s->pi.bias = s->pi.y_max;
#else
s->pi.bias = s->pi.y_min;
#endif
s->p_setpoint = 0;
s->p_adder = 0;
s->sample_n = 0;
......
......@@ -31,8 +31,13 @@ void mpll_init(struct spll_main_state *s, int id_ref,
s->pi.anti_windup = 1;
s->pi.bias = 30000;
#if defined(CONFIG_WR_SWITCH)
s->pi.kp = 1100; // / 2;
s->pi.ki = 30; // / 2;
if (ljd_present) {
s->pi.kp = 2000;
s->pi.ki = 15;
} else {
s->pi.kp = 1100; // / 2;
s->pi.ki = 30; // / 2;
}
#elif defined(CONFIG_WR_NODE)
s->pi.kp = -1100; // / 2;
s->pi.ki = -30; // / 2;
......@@ -157,11 +162,19 @@ int mpll_update(struct spll_main_state *s, int tag, int source)
if (s->ld.locked) {
if (s->phase_shift_current < s->phase_shift_target) {
s->phase_shift_current++;
#if defined(CONFIG_WR_SWITCH)
s->adder_ref++;
#else
s->adder_ref--;
#endif
} else if (s->phase_shift_current >
s->phase_shift_target) {
s->phase_shift_current--;
#if defined(CONFIG_WR_SWITCH)
s->adder_ref--;
#else
s->adder_ref++;
#endif
}
}
if (ld_update((spll_lock_det_t *)&s->ld, err))
......
......@@ -56,8 +56,11 @@ int ptrackers_update(struct spll_ptracker_state *ptrackers, int tag,
if(!s->enabled)
return 0;
#if defined(CONFIG_WR_NODE)
register int delta = (tag - tag_ref) & ((1 << HPLL_N) - 1);
#else
register int delta = (tag_ref - tag) & ((1 << HPLL_N) - 1);
#endif
register int index = delta >> (HPLL_N - 2);
......
......@@ -42,12 +42,12 @@ void help()
}
/* We don't want localized versions from ctype.h */
static int my_isalpha(char c)
static inline int my_isalpha(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
static int my_isok(char c)
static inline int my_isok(char c)
{
return c == '_' || my_isalpha(c) || (c >= '0' && c <= '9');
}
......
......@@ -18,12 +18,15 @@
the internal fabric. The frame, in the fabric, is prefixed with
a status word that includes the class bits.
The CPU is expected to receive PTP, ICMP, ARP and DHCP replies (so
local "bootpc" port).
The LM32 CPU is expected to receive PTP and if probably ICMP, ARP
and DHCP replies (so local "bootpc" port).
The fabric should receive Etherbone (i.e. UDP port 0xebd0), the
"streamer" protocol used by some CERN installation (ethtype 0xdbff)
and everything else if the "NIC pfilter" feature by 7Solutions is used.
"streamer" protocol used by some CERN installation (ethtype 0xdbff).
If an external NIC is used we should redirect everything (including
ARP,ICMP,DHCP) there excepting the PTP packets that should be handle
by LM32.
The logic cells connected to the fabric do their own check on the
frames, so it's not a problem if extra frames reach the fabric. Thus,
......@@ -416,6 +419,11 @@ void pfilter_init_novlan(char *fname)
pfilter_logic2(FRAME_UDP, FRAME_UDP, AND, FRAME_IP_OK);
pfilter_logic2(FRAME_ICMP, FRAME_ICMP, AND, FRAME_IP_OK);
#ifdef CONFIG_WR_NIC_CPU
/* For CPU: icmp unicast or ptp (or latency) */
/* Now, ARP & ICMP traffic are bypassed to the external fabric (NIC) */
pfilter_logic2(FRAME_FOR_CPU, FRAME_TYPE_PTP2, MOV, R_ZERO);
#else
/* For CPU: arp or icmp unicast or ptp (or latency) */
//pfilter_logic2(FRAME_FOR_CPU, FRAME_TYPE_ARP, OR, FRAME_TYPE_PTP2);
/* For CPU: just ptp (or latency) */
......@@ -423,6 +431,9 @@ void pfilter_init_novlan(char *fname)
//pfilter_logic3(FRAME_FOR_CPU, FRAME_IP_OK, AND, FRAME_ICMP, OR, FRAME_FOR_CPU);
/* For LM32_2ND: arp or icmp or udp */
pfilter_logic3(FRAME_FOR_2ND, FRAME_TYPE_ARP, OR, FRAME_ICMP, OR, FRAME_UDP);
#endif
/* Now look in UDP ports: at offset 18 (14 + 20 + 8 = 36) */
pfilter_cmp(18, 0x0000, 0xff00, MOV, PORT_UDP_HOST); /* ports 0-255 */
......
......@@ -30,6 +30,7 @@ static char *stats_mesg[][2] = {
{"Counter of the accumulated frequency", "acc_freq_cnt"},
{"Number of indications that one or more blocks in a"
"frame were lost (probably CRC error) since reset", "rx_cnt_lost_blk"},
{"Latency statistics with raw values for calculations", "rx_lat_raw"}
};
int read_stats(struct cmd_desc *cmdd, struct atom *atoms)
......@@ -43,10 +44,10 @@ int read_stats(struct cmd_desc *cmdd, struct atom *atoms)
if (atoms == (struct atom *)VERBOSE_HELP) {
printf("%s - options\n"
"\t0: %s\n\t1: %s\n\t2: %s\n\t3: %s\n\t4: %s\n\t5: %s\n"
"\t6: %s\n\t7: %s\n", cmdd->name, stats_mesg[0][0],
"\t6: %s\n\t7: %s\n\t8: %s\n", cmdd->name, stats_mesg[0][0],
stats_mesg[1][0], stats_mesg[2][0], stats_mesg[3][0],
stats_mesg[4][0], stats_mesg[5][0], stats_mesg[6][0],
stats_mesg[7][0]);
stats_mesg[7][0], stats_mesg[8][0]);
return 1;
}
......@@ -76,15 +77,9 @@ int read_stats(struct cmd_desc *cmdd, struct atom *atoms)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT12);
avg_lat = (((double)acc_lat) * 8 / 1000) / (double)cnt_lat;
fprintf(stderr, "Latency [us] : min=%10g max=%10g avg =%10g "
"(0x%x, 0x%x, %lu=%u << 32 | %u)*8/1000 us, "
"cnt =%lu overflow =%d)\n",
min_lat, max_lat, avg_lat,
iomemr32(wrstm->is_be, ptr->RX_STAT1),
iomemr32(wrstm->is_be, ptr->RX_STAT0),
acc_lat, iomemr32(wrstm->is_be, ptr->RX_STAT11),
iomemr32(wrstm->is_be, ptr->RX_STAT10),
cnt_lat, overflow);
fprintf(stderr, "Frames [number]: tx =%lu rx =%lu lost=%lu "
"(overflow =%d)\n",
min_lat, max_lat, avg_lat, overflow);
fprintf(stderr, "Frames [number]: tx =%10lu rx =%10lu lost=%10lu "
"(lost blocks =%lu)\n",
((uint64_t)iomemr32(wrstm->is_be, ptr->TX_STAT3)
<< 32) | iomemr32(wrstm->is_be, ptr->TX_STAT2),
......@@ -135,6 +130,30 @@ int read_stats(struct cmd_desc *cmdd, struct atom *atoms)
((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT9)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT8));
break;
case 8:
max_lat = WR_STREAMERS_RX_STAT0_RX_LATENCY_MAX_R(
iomemr32(wrstm->is_be, ptr->RX_STAT0));
max_lat = (max_lat * 8) / 1000.0;
min_lat = WR_STREAMERS_RX_STAT1_RX_LATENCY_MIN_R(
iomemr32(wrstm->is_be, ptr->RX_STAT1));
min_lat = (min_lat * 8) / 1000.0;
overflow = WR_STREAMERS_SSCR1_RX_LATENCY_ACC_OVERFLOW &
iomemr32(wrstm->is_be, ptr->SSCR1);
//put it all together
acc_lat = ((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT11)
<< 32) |iomemr32(wrstm->is_be, ptr->RX_STAT10);
cnt_lat = ((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT13)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT12);
avg_lat = (((double)acc_lat) * 8 / 1000) / (double)cnt_lat;
fprintf(stderr, "%s: min=%10g max=%10g avg =%10g "
"(0x%x, 0x%x, %lu=%u << 32 | %u)*8/1000 us, "
"cnt =%lu overflow =%d)\n", stats_mesg[8][1],
min_lat, max_lat, avg_lat,
iomemr32(wrstm->is_be, ptr->RX_STAT1),
iomemr32(wrstm->is_be, ptr->RX_STAT0),
acc_lat, iomemr32(wrstm->is_be, ptr->RX_STAT11),
iomemr32(wrstm->is_be, ptr->RX_STAT10),
cnt_lat, overflow);
}
//release snapshot
......@@ -206,6 +225,23 @@ int reset_seqid(struct cmd_desc *cmdd, struct atom *atoms)
return 1;
}
int hdl_sw_reset(struct cmd_desc *cmdd, struct atom *atoms)
{
volatile struct WR_STREAMERS_WB *ptr =
(volatile struct WR_STREAMERS_WB *)wrstm->base;
if (atoms == (struct atom *)VERBOSE_HELP) {
printf("%s - %s\n", cmdd->name, cmdd->help);
return 1;
}
ptr->RSTR = iomemw32(wrstm->is_be, WR_STREAMERS_RSTR_RST_SW);
fprintf(stderr, "Reseted the tx and rx wr_streamer HDL modules \n"
"(streamer statistics are not affected and require "
"reset)\n");
return 1;
}
int get_set_tx_ethertype(struct cmd_desc *cmdd, struct atom *atoms)
{
volatile struct WR_STREAMERS_WB *ptr =
......@@ -420,6 +456,80 @@ int get_set_latency(struct cmd_desc *cmdd, struct atom *atoms)
return 1;
}
int get_latency_stats(struct cmd_desc *cmdd, struct atom *atoms)
{
volatile struct WR_STREAMERS_WB *ptr =
(volatile struct WR_STREAMERS_WB *)wrstm->base;
if (atoms == (struct atom *)VERBOSE_HELP) {
printf("%s - %s\n", cmdd->name, cmdd->help);
return 1;
}
//snapshot stats
ptr->SSCR1 = iomemw32(wrstm->is_be, WR_STREAMERS_SSCR1_SNAPSHOT_STATS);
fprintf(stderr, "Fixed latency frames [number]: "
"match = %10lu "
"late = %10lu "
"timeout = %10lu\n",
((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT20)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT19),
((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT16)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT15),
((uint64_t)iomemr32(wrstm->is_be, ptr->RX_STAT18)
<< 32) | iomemr32(wrstm->is_be, ptr->RX_STAT17)
);
//release snapshot
ptr->SSCR1 = 0;
return 1;
}
int get_set_latency_timeout(struct cmd_desc *cmdd, struct atom *atoms)
{
volatile struct WR_STREAMERS_WB *ptr =
(volatile struct WR_STREAMERS_WB *)wrstm->base;
int lat;
uint32_t val;
if (atoms == (struct atom *)VERBOSE_HELP) {
printf("%s - %s\n", cmdd->name, cmdd->help);
return 1;
}
++atoms;
if (atoms->type == Terminator) {
// Get Latency
val = WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_R(
iomemr32(wrstm->is_be, ptr->RX_CFG6));
fprintf(stderr, "Fixed latency timeout: %d [us]\n",
(val * 8) / 1000);
}
else {
if (atoms->type != Numeric)
return -TST_ERR_WRONG_ARG;
lat = atoms->val;
if (lat < 0) {
val = 0x1000000;
lat = (val * 8) / 1000;
fprintf(stderr, "Setting default value of ~134ms\n");
}
else{
val = (lat * 1000) / 8;
}
ptr->RX_CFG6 = iomemw32(wrstm->is_be,
WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_W(val));
val = WR_STREAMERS_RX_CFG6_RX_FIXED_LATENCY_TIMEOUT_R(
iomemr32(wrstm->is_be, ptr->RX_CFG6));
fprintf(stderr, "Fixed latency timeout set: %d [us] "
"(set %d | read : %d [8ns cycles])\n",
lat, ((lat * 1000) / 8), val);
}
return 1;
}
int get_set_qtags_flag(struct cmd_desc *cmdd, struct atom *atoms)
{
volatile struct WR_STREAMERS_WB *ptr =
......@@ -573,6 +683,8 @@ enum wrstm_cmd_id{
WRSTM_CMD_RX_REM_MAC,
*/
WRSTM_CMD_LATENCY,
WRSTM_CMD_LATENCY_STATS,
WRSTM_CMD_LATENCY_TIMEOUT,
WRSTM_CMD_QTAG_ENB,
WRSTM_CMD_QTAG_VP,
WRSTM_CMD_QTAG_OR,
......@@ -580,6 +692,7 @@ enum wrstm_cmd_id{
// WRSTM_CMD_DBG_BYTE,
// WRSTM_CMD_DBG_MUX,
// WRSTM_CMD_DBG_VAL,
WRSTM_CMD_HDL_SW_RESET,
WRSTM_CMD_LAST,
};
......@@ -619,9 +732,15 @@ struct cmd_desc wrstm_cmd[WRSTM_CMD_NB + 1] = {
{ 1, WRSTM_CMD_TX_ETHERTYPE, "txether",
"get/set TX ethertype", "ethertype", 0, get_set_tx_ethertype},
**************************************************************** */
{ 1, WRSTM_CMD_LATENCY, "lat",
{ 1, WRSTM_CMD_LATENCY, "flat",
"get/set config of fixed latency in integer [us] (-1 to disable)",
"[latency]", 0, get_set_latency},
"[fixed latency value]", 0, get_set_latency},
{ 1, WRSTM_CMD_LATENCY_STATS, "flatstats",
"get statistics regarding fixed latency operation",
"", 0, get_latency_stats},
{ 1, WRSTM_CMD_LATENCY_TIMEOUT, "flattimeout",
"get/set fixed latency timeout [us] (-1 to set default: ~1ms)",
"[timeout value]", 0, get_set_latency_timeout},
{ 1, WRSTM_CMD_QTAG_ENB, "qtagf",
"QTags flag on off",
"[0/1]", 0, get_set_qtags_flag},
......@@ -641,6 +760,9 @@ struct cmd_desc wrstm_cmd[WRSTM_CMD_NB + 1] = {
// "set whether tx or rx frames should be snooped", "dir", 1,},
// { 1, WRSTM_CMD_DBG_VAL, "dbgword",
// "read the snooped 32-bit value", "", 0,},
{ 1, WRSTM_CMD_HDL_SW_RESET, "hdlswreset",
"HD software reset of rx and tx streamer HDL modules (excludes stats)",
"", 0, hdl_sw_reset},
{0, },
};
......@@ -700,9 +822,10 @@ int main(int argc, char *argv[])
ret = verify_reg_version();
if (ret) {
fprintf(stderr, "============== !!! WARNING !!! ===============\n");
fprintf(stderr, "Register version in FPGA and SW does not match\n");
dev_unmap(wrstm);
return -1;
fprintf(stderr, " Using SW at your own risk \n");
fprintf(stderr, "============== !!! WARNING !!! ===============\n");
}
ret = extest_register_user_cmd(wrstm_cmd, WRSTM_CMD_NB);
......
......@@ -15,6 +15,10 @@
#include <hw/wb_uart.h>
#include <libdevmap.h>
#define VUART_EOL 13
#define VUART_CMD_USLEEP 1000000
#define VUART_CMD_PROMPT "wrc#"
static void wrpc_vuart_help(char *prog)
{
const char *mapping_help_str;
......@@ -80,6 +84,19 @@ static size_t wr_vuart_read(struct mapping_desc *vuart, char *buf, size_t size)
return n_rx;
}
/**
* It flush vuart buffer.
*
* @param[in] vuart token from dev_map()
*
*/
static void wr_vuart_flush(struct mapping_desc *vuart)
{
char rx;
while(wr_vuart_read(vuart,&rx,1) == 1) {}
}
/**
* It writes a number of bytes from a given buffer
* @param[in] vuart token from dev_map()
......@@ -99,16 +116,22 @@ static size_t wr_vuart_write(struct mapping_desc *vuart, char *buf, size_t size)
return size;
}
static void wrpc_vuart_term_main(struct mapping_desc *vuart, int keep_term)
static void wrpc_vuart_term_main(struct mapping_desc *vuart, int keep_term, int command_mode, char *command)
{
struct termios oldkey, newkey;
//above is place for old and new port settings for keyboard teletype
int need_exit = 0;
int cmd_sent = 0;
int cmd_len = 0;
char *prompt = VUART_CMD_PROMPT;
int i_prompt = 0;
int i;
fd_set fds;
int ret;
char rx, tx;
fprintf(stderr, "[press C-a to exit]\n");
if(!command_mode)
fprintf(stderr, "[press C-a to exit]\n");
if(!keep_term) {
tcgetattr(STDIN_FILENO,&oldkey);
......@@ -122,49 +145,102 @@ static void wrpc_vuart_term_main(struct mapping_desc *vuart, int keep_term)
tcsetattr(STDIN_FILENO,TCSANOW,&newkey);
}
while(!need_exit) {
struct timeval tv = {0, 10000};
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
/*
* Check if the STDIN has characters to read
* (what the user writes)
*/
ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
switch (ret) {
case -1:
perror("select");
break;
case 0: /* timeout */
break;
default:
if(!FD_ISSET(STDIN_FILENO, &fds))
if (!command_mode) {
struct timeval tv = {0, 10000};
FD_ZERO(&fds);
FD_SET(STDIN_FILENO, &fds);
/*
* Check if the STDIN has characters to read
* (what the user writes)
*/
ret = select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv);
switch (ret) {
case -1:
perror("select");
break;
case 0: /* timeout */
break;
default:
if(!FD_ISSET(STDIN_FILENO, &fds))
break;
/* The user wrote something */
do {
ret = read(STDIN_FILENO, &tx, 1);
} while (ret < 0 && errno == EINTR);
if (ret != 1) {
fprintf(stderr, "nothing to read. Port disconnected?\n");
need_exit = 1; /* kill */
}
/* If the user character is C-a, then kill */
if(tx == '\x01')
need_exit = 1;
ret = wr_vuart_write(vuart, &tx, 1);
if (ret != 1) {
fprintf(stderr, "Unable to write (errno: %d)\n", errno);
need_exit = 1;
}
break;
/* The user wrote something */
do {
ret = read(STDIN_FILENO, &tx, 1);
} while (ret < 0 && errno == EINTR);
if (ret != 1) {
fprintf(stderr, "nothing to read. Port disconnected?\n");
need_exit = 1; /* kill */
}
/* If the user character is C-a, then kill */
if(tx == '\x01')
need_exit = 1;
ret = wr_vuart_write(vuart, &tx, 1);
if (ret != 1) {
fprintf(stderr, "Unable to write (errno: %d)\n", errno);
need_exit = 1;
} else {
if(!cmd_sent) {
/* Flush Vuart before sending command */
wr_vuart_flush(vuart);
/* Send command */
cmd_len = strlen(command);
ret = wr_vuart_write(vuart, command, cmd_len-1);
if (ret != cmd_len-1) {
fprintf(stderr, "Unable to write the command (errno: %d)\n",errno);
need_exit = 1;
}
/* Flush command echo */
wr_vuart_flush(vuart);
/* Send end character */
ret = wr_vuart_write(vuart, &command[cmd_len-1], 1);
if (ret != 1) {
fprintf(stderr, "Unable to write the end character of command (errno: %d)\n",errno);
need_exit = 1;
}
/* Wait for a while before reading command results */
usleep(VUART_CMD_USLEEP);
/* Discard characters until end of line control one */
while(wr_vuart_read(vuart, &rx, 1)) {
if(rx == VUART_EOL)
break;
}
cmd_sent = 1;
}
break;
}
/* Print all the incoming charactes */
while((wr_vuart_read(vuart, &rx, 1)) == 1)
fprintf(stderr,"%c", rx);
while((wr_vuart_read(vuart, &rx, 1)) == 1) {
if (command_mode == 1) {
/* Prompt detection, skip characters */
if (rx == prompt[i_prompt]) {
i_prompt++;
/* Prompt detected! */
if(i_prompt == strlen(prompt)) {
need_exit = 1;
break;
}
} else {
/* Check if some previous characters have been skipped by
prompt detector code and print them */
for(i = 0 ; i < i_prompt ; i++)
fprintf(stderr,"%c",prompt[i]);
/* Reset prompt detector */
i_prompt = 0;
/* Print current character */
fprintf(stderr,"%c", rx);
}
} else {
fprintf(stderr,"%c",rx);
}
}
}
if(!keep_term)
......@@ -176,6 +252,9 @@ int main(int argc, char *argv[])
{
char c;
int keep_term = 0;
int command_mode = 0;
char cmd[50];
int cmd_len = 0;
struct mapping_args *map_args;
struct mapping_desc *vuart = NULL;
......@@ -186,8 +265,18 @@ int main(int argc, char *argv[])
}
/* Parse specific args */
while ((c = getopt (argc, argv, "k")) != -1) {
while ((c = getopt (argc, argv, "c:k")) != -1) {
switch (c) {
case 'c':
/* Enable command mode */
command_mode = 1;
/* Get the command from args */
strcpy(cmd, optarg);
cmd_len = strlen(cmd);
/* Put end of buffer for terminal */
cmd[cmd_len] = VUART_EOL;
cmd[cmd_len+1] = 0;
break;
case 'k':
keep_term = 1;
break;
......@@ -206,7 +295,7 @@ int main(int argc, char *argv[])
goto out;
}
wrpc_vuart_term_main(vuart, keep_term);
wrpc_vuart_term_main(vuart, keep_term, command_mode, cmd);
dev_unmap(vuart);
return 0;
......
......@@ -30,6 +30,7 @@
#include "lib/ipv4.h"
#include "rxts_calibrator.h"
#include "flash.h"
#include "fram.h"
#include "wrc_ptp.h"
#include "system_checks.h"
......@@ -64,9 +65,10 @@ static void wrc_initialize(void)
timer_init(1);
get_hw_name(wrc_hw_name);
#ifdef CONFIG_SDB_STORAGE
storage_read_hdl_cfg();
#endif
if (HAS_GENSDBFS)
storage_read_hdl_cfg();
wrpc_w1_init();
wrpc_w1_bus.detail = ONEWIRE_PORT;
w1_scan_bus(&wrpc_w1_bus);
......@@ -238,6 +240,17 @@ DEFINE_WRC_TASK(wrx_Execute) = {
.job = wrx_Execute,
};
void wrx_Execute()
{
wrxUpdate(link_status);
wrxExecute();
}
DEFINE_WRC_TASK(wrx_Execute) = {
.name = "wrx-exec",
.job = wrx_Execute,
};
static void task_time_normalize(struct wrc_task *t)
{
if (t->nanos > 1000 * 1000 * 1000) {
......
......@@ -13,6 +13,7 @@
#include "minipc.h"
#include "revision.h"
#include "system_checks.h"
#include "gpio-wrs.h"
int scb_ver = 33; /* SCB version */
......@@ -40,6 +41,12 @@ int main(void)
build_revision, build_date, build_time);
pp_printf("SCB version: %d. %s\n", scb_ver,(scb_ver>=34)?"10 MHz SMC Output.":"" );
pp_printf("Start counter %d\n", stats.start_cnt);
/* Low-jitter Daughterboard detection */
ljd_present = gpio_in(GPIO_LJD_BOARD_DETECT);
if (ljd_present) {
pp_printf("\n--- WRS Low jitter board detected. ---\n");
pp_printf("Allow 1 hour of warming up before starting measurements\n");
}
pp_printf("--\n");
if (stats.start_cnt > 1) {
......@@ -47,7 +54,7 @@ int main(void)
/* for sure problem is in calling second time ad9516_init,
* but not only */
}
ad9516_init(scb_ver);
ad9516_init(scb_ver, ljd_present);
rts_init();
rtipc_init();
spll_very_init();
......
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