Merge pull request #333 from slsdetectorgroup/3kernelupdate

3kernelupdate
This commit is contained in:
Dhanya Thattil
2021-11-17 10:10:19 +01:00
committed by GitHub
53 changed files with 1776 additions and 1072 deletions

View File

@@ -137,7 +137,6 @@ sls_enable_cxx_warning("-Wnull-dereference")
sls_enable_cxx_warning("-Wduplicated-cond")
sls_disable_cxx_warning("-Wclass-memaccess")
sls_disable_c_warning("-Wstringop-truncation")
sls_disable_c_warning("-Wformat-nonliteral")
if(SLS_USE_SANITIZER)

View File

@@ -20,7 +20,9 @@ This document describes the differences between vx.x.x and v6.0.0.
1. New or Changed Features
==========================
- kernelversion
- updatekernel
- updatedetectorserver
- update (without pcname)
2. Resolved Issues
@@ -30,6 +32,8 @@ This document describes the differences between vx.x.x and v6.0.0.
- rx id in config file was not taken into account. fixed.
- programming firmware failure for blackfin, fixed but requires new kernel.
- nios kernel check updated (ensuring right kernel)
- executecommand now says which module failed
- programming firmware did not delete temporary file created. fixed.
3. Known Issues
===============

View File

@@ -1520,7 +1520,15 @@ void init_det(py::module &m) {
(void (Detector::*)(const std::string &, const std::string &,
sls::Positions)) &
Detector::copyDetectorServer,
py::arg(), py::arg(), py::arg() = Positions{})
py::arg(), py::arg(), py::arg() = Positions{})
.def("updateDetectorServer",
(void (Detector::*)(const std::string &, sls::Positions)) &
Detector::updateDetectorServer,
py::arg(), py::arg() = Positions{})
.def("updateKernel",
(void (Detector::*)(const std::string &, sls::Positions)) &
Detector::updateKernel,
py::arg(), py::arg() = Positions{})
.def("rebootController",
(void (Detector::*)(sls::Positions)) & Detector::rebootController,
py::arg() = Positions{})
@@ -1529,6 +1537,11 @@ void init_det(py::module &m) {
const std::string &, sls::Positions)) &
Detector::updateFirmwareAndServer,
py::arg(), py::arg(), py::arg(), py::arg() = Positions{})
.def("updateFirmwareAndServer",
(void (Detector::*)(const std::string &, const std::string &,
sls::Positions)) &
Detector::updateFirmwareAndServer,
py::arg(), py::arg(), py::arg() = Positions{})
.def("readRegister",
(Result<uint32_t>(Detector::*)(uint32_t, sls::Positions) const) &
Detector::readRegister,

View File

@@ -17,7 +17,7 @@ add_executable(ctbDetectorServer_virtual
../slsDetectorServer/src/INA226.c
../slsDetectorServer/src/LTC2620.c
../slsDetectorServer/src/MAX1932.c
../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/programViaBlackfin.c
../slsDetectorServer/src/sharedMemory.c
../slsDetectorServer/src/loadPattern.c
../../slsSupportLib/src/md5.c

View File

@@ -16,7 +16,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD7689.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)I2C.c $(main_src)INA226.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)

View File

@@ -97,8 +97,14 @@ void basictests() {
return;
#else
defineGPIOpins();
resetFPGA();
initError = defineGPIOpins(initErrorMessage);
if (initError == FAIL) {
return;
}
initError = resetFPGA(initErrorMessage);
if (initError == FAIL) {
return;
}
if (mapCSP0() == FAIL) {
strcpy(initErrorMessage,
"Could not map to memory. Dangerous to continue.\n");

View File

@@ -3,7 +3,7 @@
#pragma once
#include "sls/sls_detector_defs.h"
#define LINKED_SERVER_NAME "eigerDetectorServer"
#define LINKED_SERVER_NAME "/home/root/executables/eigerDetectorServer"
#define REQUIRED_FIRMWARE_VERSION (29)
// virtual ones renamed for consistency

View File

@@ -12,7 +12,7 @@ add_executable(gotthard2DetectorServer_virtual
../slsDetectorServer/src/LTC2620_Driver.c
../slsDetectorServer/src/ALTERA_PLL_CYCLONE10.c
../slsDetectorServer/src/ASIC_Driver.c
../slsDetectorServer/src/programFpgaNios.c
../slsDetectorServer/src/programViaNios.c
../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c
)

View File

@@ -15,7 +15,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)common.c $(main_src)DAC6571.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)ASIC_Driver.c $(main_src)/programViaNios.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)

View File

@@ -11,6 +11,7 @@ add_executable(gotthardDetectorServer_virtual
../slsDetectorServer/src/LTC2620.c
../slsDetectorServer/src/common.c
../slsDetectorServer/src/commonServerFunctions.c
../slsDetectorServer/src/programViaBlackfin.c
../slsDetectorServer/src/communication_funcs_UDP.c
../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c

View File

@@ -15,7 +15,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)AD9252.c $(main_src)AD9257.c $(main_src)LTC2620.c $(main_src)programViaBlackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)
all: clean $(PROGS)

View File

@@ -6,6 +6,8 @@
#define LINKED_SERVER_NAME "gotthardDetectorServer"
#define CTRL_SRVR_INIT_TIME_US (300 * 1000)
/* Enums */
enum ADCINDEX { TEMP_FPGA, TEMP_ADC };
enum DACINDEX {

View File

@@ -12,7 +12,7 @@ add_executable(jungfrauDetectorServer_virtual
../slsDetectorServer/src/ALTERA_PLL.c
../slsDetectorServer/src/LTC2620.c
../slsDetectorServer/src/MAX1932.c
../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/programViaBlackfin.c
../slsDetectorServer/src/communication_funcs_UDP.c
../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c

View File

@@ -15,7 +15,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)

View File

@@ -74,8 +74,14 @@ void basictests() {
}
return;
#else
defineGPIOpins();
resetFPGA();
initError = defineGPIOpins(initErrorMessage);
if (initError == FAIL) {
return;
}
initError = resetFPGA(initErrorMessage);
if (initError == FAIL) {
return;
}
if (mapCSP0() == FAIL) {
strcpy(initErrorMessage,
"Could not map to memory. Dangerous to continue.\n");

View File

@@ -14,7 +14,7 @@ add_executable(moenchDetectorServer_virtual
../slsDetectorServer/src/ALTERA_PLL.c
../slsDetectorServer/src/LTC2620.c
../slsDetectorServer/src/MAX1932.c
../slsDetectorServer/src/programFpgaBlackfin.c
../slsDetectorServer/src/programViaBlackfin.c
../slsDetectorServer/src/loadPattern.c
../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c

View File

@@ -16,7 +16,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programFpgaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)blackfin.c $(main_src)common.c $(main_src)commonServerFunctions.c $(main_src)communication_funcs_UDP.c $(main_src)UDPPacketHeaderGenerator.c $(main_src)AD9257.c $(main_src)ALTERA_PLL.c $(main_src)LTC2620.c $(main_src)MAX1932.c $(main_src)programViaBlackfin.c $(main_src)loadPattern.c $(main_src)/sharedMemory.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)

View File

@@ -94,8 +94,14 @@ void basictests() {
return;
#else
defineGPIOpins();
resetFPGA();
initError = defineGPIOpins(initErrorMessage);
if (initError == FAIL) {
return;
}
initError = resetFPGA(initErrorMessage);
if (initError == FAIL) {
return;
}
if (mapCSP0() == FAIL) {
strcpy(initErrorMessage,
"Could not map to memory. Dangerous to continue.\n");

View File

@@ -12,7 +12,7 @@ add_executable(mythen3DetectorServer_virtual
../slsDetectorServer/src/common.c
../slsDetectorServer/src/LTC2620_Driver.c
../slsDetectorServer/src/ALTERA_PLL_CYCLONE10.c
../slsDetectorServer/src/programFpgaNios.c
../slsDetectorServer/src/programViaNios.c
../slsDetectorServer/src/loadPattern.c
../slsDetectorServer/src/sharedMemory.c
../../slsSupportLib/src/md5.c

View File

@@ -16,7 +16,7 @@ DESTDIR ?= bin
INSTMODE = 0777
SRCS = slsDetectorFunctionList.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programFpgaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c $(md5_dir)md5.c
SRCS += $(main_src)slsDetectorServer.c $(main_src)slsDetectorServer_funcs.c $(main_src)communication_funcs.c $(main_src)nios.c $(main_src)DAC6571.c $(main_src)common.c $(main_src)LTC2620_Driver.c $(main_src)ALTERA_PLL_CYCLONE10.c $(main_src)/programViaNios.c $(main_src)/sharedMemory.c $(main_src)/loadPattern.c mythen3.c $(md5_dir)md5.c
OBJS = $(SRCS:.c=.o)

View File

@@ -8,7 +8,12 @@
#include <sys/types.h>
#include <time.h>
#define TEMP_PROG_FOLDER_NAME "/var/tmp/"
#define TEMP_PROG_FOLDER_NAME_ALL_FILES "/var/tmp/*"
#define TEMP_PROG_FILE_NAME TEMP_PROG_FOLDER_NAME "tmp.rawbin"
enum numberMode { DEC, HEX };
enum PROGRAM_INDEX { PROGRAM_FPGA, PROGRAM_KERNEL, PROGRAM_SERVER };
/**
* Convert a value from a range to a different range (eg voltage to dac or vice
@@ -28,7 +33,7 @@ int getAbsPath(char *buf, size_t bufSize, char *fname);
int getTimeFromString(char *buf, time_t *result);
int getKernelVersion(char* retvals);
int getKernelVersion(char *retvals);
int validateKernelVersion(char *expectedVersion);
@@ -38,9 +43,17 @@ void validate64(int *ret, char *mess, int64_t arg, int64_t retval,
char *modename, enum numberMode nummode);
int getModuleIdInFile(int *ret, char *mess, char *fileName);
int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer,
ssize_t bytes);
int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname);
int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
ssize_t fsize);
int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg);
int verifyChecksumFromBuffer(char *mess, char *functionType,
char *clientChecksum, char *buffer, ssize_t bytes);
int verifyChecksumFromFile(char *mess, char *functionType, char *clientChecksum,
char *fname);
int verifyChecksumFromFlash(char *mess, char *functionType,
char *clientChecksum, char *fname, ssize_t fsize);
int verifyChecksum(char *mess, char *functionType, char *clientChecksum,
MD5_CTX *c, char *msg);
int setupDetectorServer(char *mess, char *sname);
int writeBinaryFile(char *mess, char *fname, char *buffer,
const uint64_t filesize, char *errorPrefix);
int moveBinaryFile(char *mess, char *dest, char *src, char *errorPrefix);

View File

@@ -1,32 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
#define TEMP_PROG_FILE_NAME "/var/tmp/tmp.rawbin"
void defineGPIOpins();
void FPGAdontTouchFlash();
void FPGATouchFlash();
void resetFPGA();
int deleteOldFile(char *mess);
/**
* deletes old file
* verify memory available to copy
* open file to copy
*/
int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess);
int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess);
int getDrive(char *mess);
/** Notify fpga not to touch flash, open src and flash drive to write */
int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess);
int eraseFlash(char *mess);
/* write from tmp file to flash */
int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess);
/** Notify fpga to pick up firmware from flash and wait for status confirmation
*/
int waitForFPGAtoTouchFlash(char *mess);

View File

@@ -0,0 +1,35 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include "common.h"
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
int defineGPIOpins(char *mess);
int FPGAdontTouchFlash(char *mess);
int FPGATouchFlash(char *mess);
int resetFPGA(char *mess);
int emptyTempFolder(char *mess);
/**
* deletes old file
* verify memory available to copy
* open file to copy
*/
int preparetoCopyProgram(char *mess, char *functionType, FILE **fd,
uint64_t fsize);
int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index,
char *functionType, char *clientChecksum,
ssize_t fsize);
int getDrive(char *mess, enum PROGRAM_INDEX index);
/** Notify fpga not to touch flash, open src and flash drive to write */
int openFileForFlash(char *mess, FILE **flashfd, FILE **srcfd);
int eraseFlash(char *mess);
/* write from tmp file to flash */
int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, FILE *srcfd);
/** Notify fpga to pick up firmware from flash and wait for status confirmation
*/
int waitForFPGAtoTouchFlash(char *mess);

View File

@@ -2,6 +2,8 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include "common.h"
#include <stdint.h>
#include <stdio.h>
@@ -13,9 +15,10 @@ void NotifyServerStartSuccess();
/** reset fpga and controller(only implemented for >= v1.1 boards) */
void rebootControllerAndFPGA();
int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc,
int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index,
char *functionType, char *checksum, char *fpgasrc,
uint64_t fsize);
int getDrive(char *mess);
int openFileForFlash(FILE **flashfd, char *mess);
int getDrive(char *mess, enum PROGRAM_INDEX index);
int openFileForFlash(char *mess, FILE **flashfd);
int eraseFlash(char *mess);
int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess);
int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, char *buffer);

View File

@@ -12,9 +12,10 @@
#endif
#if defined(MYTHEN3D) || defined(GOTTHARD2D)
#include "programFpgaNios.h"
#elif defined(CHIPTESTBOARDD) || defined(JUNGFRAUD) || defined(MOENCHD)
#include "programFpgaBlackfin.h"
#include "programViaNios.h"
#elif defined(CHIPTESTBOARDD) || defined(JUNGFRAUD) || defined(MOENCHD) || \
defined(GOTTHARDD)
#include "programViaBlackfin.h"
#endif
#if defined(MYTHEN3D) || defined(GOTTHARD2D)
@@ -60,7 +61,6 @@ typedef struct udpStruct_s {
int isInitCheckDone();
int getInitResult(char **mess);
void basictests();
int getKernelVersion(char* retvals);
#if defined(GOTTHARDD) || defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || \
defined(MOENCHD) || defined(MYTHEN3D) || defined(GOTTHARD2D)
int checkType();

View File

@@ -277,4 +277,13 @@ int get_udp_first_dest(int);
int set_udp_first_dest(int);
int get_readout_speed(int);
int set_readout_speed(int);
int get_kernel_version(int);
int get_kernel_version(int);
int update_kernel(int);
int update_detector_server(int);
int receive_program(int file_des, enum PROGRAM_INDEX index);
void receive_program_via_blackfin(int file_des, enum PROGRAM_INDEX index,
char *functionType, uint64_t filesize,
char *checksum, char *serverName);
void receive_program_default(int file_des, enum PROGRAM_INDEX index,
char *functionType, uint64_t filesize,
char *checksum, char *serverName);

View File

@@ -4,12 +4,15 @@
#include "common.h"
#include "clogger.h"
#include "sls/sls_detector_defs.h"
#include "slsDetectorServer_defs.h"
#include <libgen.h> // dirname
#include <string.h>
#include <sys/utsname.h> // uname
#include <unistd.h> // readlink
extern int executeCommand(char *command, char *result, enum TLogLevel level);
int ConvertToDifferentRange(int inputMin, int inputMax, int outputMin,
int outputMax, int inputValue, int *outputValue) {
LOG(logDEBUG1, (" Input Value: %d (Input:(%d - %d), Output:(%d - %d))\n",
@@ -92,19 +95,22 @@ int getTimeFromString(char *buf, time_t *result) {
}
// print time structure
LOG(logDEBUG, ("%d %d %d %d:%d:%d %d (day date month H:M:S year)\n", t.tm_wday, t.tm_mday, t.tm_mon, t.tm_year +1900, t.tm_hour, t.tm_min, t.tm_sec));
LOG(logDEBUG,
("%d %d %d %d:%d:%d %d (day date month H:M:S year)\n", t.tm_wday,
t.tm_mday, t.tm_mon, t.tm_year + 1900, t.tm_hour, t.tm_min, t.tm_sec));
*result = mktime(&t);
return OK;
}
int getKernelVersion(char* retvals) {
struct utsname buf = {0};
int getKernelVersion(char *retvals) {
struct utsname buf;
memset(&buf, 0, sizeof(buf));
if (uname(&buf) == -1) {
strcpy(retvals, "Failed to get utsname structure from uname\n");
LOG(logERROR, (retvals));
return FAIL;
}
}
strcpy(retvals, buf.version);
LOG(logINFOBLUE, ("Kernel Version: %s\n", retvals));
return OK;
@@ -135,7 +141,8 @@ int validateKernelVersion(char *expectedVersion) {
// convert kernel date string into time
time_t kernelDate;
if (getTimeFromString(currentVersion, &kernelDate) == FAIL) {
LOG(logERROR, ("Could not parse retrieved kernel date, %s\n", currentVersion));
LOG(logERROR,
("Could not parse retrieved kernel date, %s\n", currentVersion));
return FAIL;
}
@@ -155,8 +162,8 @@ int validateKernelVersion(char *expectedVersion) {
return FAIL;
}
LOG(logINFOBLUE, ("Kernel Version Compatible: %s [min.: %s]\n", currentVersion,
expectedVersion));
LOG(logINFOBLUE, ("Kernel Version Compatible: %s [min.: %s]\n",
currentVersion, expectedVersion));
return OK;
}
@@ -235,30 +242,39 @@ int getModuleIdInFile(int *ret, char *mess, char *fileName) {
return retval;
}
int verifyChecksumFromBuffer(char *mess, char *clientChecksum, char *buffer,
int verifyChecksumFromBuffer(char *mess, char *functionType,
char *clientChecksum, char *buffer,
ssize_t bytes) {
LOG(logINFO, ("\tVerifying Checksum...\n"));
LOG(logINFO, ("\tVerifying Checksum from memory...\n"));
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
sprintf(mess,
"Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
if (!MD5_Update_SLS(&c, buffer, bytes)) {
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
sprintf(mess,
"Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
return verifyChecksum(mess, clientChecksum, &c, "copied program");
return verifyChecksum(mess, functionType, clientChecksum, &c,
"copied program (buffer)");
}
int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) {
LOG(logINFO, ("\tVerifying Checksum...\n"));
int verifyChecksumFromFile(char *mess, char *functionType, char *clientChecksum,
char *fname) {
LOG(logINFO, ("\tVerifying Checksum of file...\n"));
FILE *fp = fopen(fname, "r");
if (fp == NULL) {
sprintf(mess, "Unable to open %s in read mode to get checksum\n",
fname);
sprintf(
mess,
"Could not %s. Unable to open %s in read mode to get checksum\n",
functionType, fname);
LOG(logERROR, (mess));
return FAIL;
}
@@ -266,7 +282,9 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) {
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
sprintf(mess,
"Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
@@ -277,7 +295,10 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) {
while (bytes > 0) {
if (!MD5_Update_SLS(&c, buf, bytes)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
sprintf(
mess,
"Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
@@ -286,17 +307,20 @@ int verifyChecksumFromFile(char *mess, char *clientChecksum, char *fname) {
}
LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead));
fclose(fp);
return verifyChecksum(mess, clientChecksum, &c, "copied program");
return verifyChecksum(mess, functionType, clientChecksum, &c,
"copied program (file)");
}
int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
ssize_t fsize) {
LOG(logINFO, ("\tVerifying FlashChecksum...\n"));
int verifyChecksumFromFlash(char *mess, char *functionType,
char *clientChecksum, char *fname, ssize_t fsize) {
LOG(logINFO, ("\tVerifying Checksum from flash...\n"));
FILE *fp = fopen(fname, "r");
if (fp == NULL) {
sprintf(mess, "Unable to open %s in read mode to get checksum\n",
fname);
sprintf(
mess,
"Could not %s. Unable to open %s in read mode to get checksum\n",
functionType, fname);
LOG(logERROR, (mess));
return FAIL;
}
@@ -304,7 +328,9 @@ int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
MD5_CTX c;
if (!MD5_Init_SLS(&c)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Init_SLS)\n");
sprintf(mess,
"Could not %s. Unable to calculate checksum (MD5_Init_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
@@ -324,33 +350,39 @@ int verifyChecksumFromFlash(char *mess, char *clientChecksum, char *fname,
if (!MD5_Update_SLS(&c, buf, bytes)) {
fclose(fp);
strcpy(mess, "Unable to calculate checksum (MD5_Update_SLS)\n");
sprintf(
mess,
"Could not %s. Unable to calculate checksum (MD5_Update_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
// read only until a particular size (drive)
if (fsize != 0 && totalBytesRead >= fsize) {
LOG(logINFO,
("\tReached %lu bytes. Not reading more\n", totalBytesRead));
break;
}
bytes = fread(buf, 1, readUnitSize, fp);
// for less than 128 bytes
ssize_t bytesToRead = readUnitSize;
if ((readUnitSize + totalBytesRead) > fsize) {
bytesToRead = fsize - totalBytesRead;
}
bytes = fread(buf, 1, bytesToRead, fp);
totalBytesRead += bytes;
}
LOG(logINFO, ("\tRead %lu bytes to calculate checksum\n", totalBytesRead));
fclose(fp);
int ret = verifyChecksum(mess, clientChecksum, &c, "flash");
if (ret == OK) {
LOG(logINFO, ("Checksum in Flash verified\n"));
}
return ret;
return verifyChecksum(mess, functionType, clientChecksum, &c, "flash");
}
int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg) {
int verifyChecksum(char *mess, char *functionType, char *clientChecksum,
MD5_CTX *c, char *msg) {
unsigned char out[MD5_DIGEST_LENGTH];
if (!MD5_Final_SLS(out, c)) {
strcpy(mess, "Unable to calculate checksum (MD5_Final_SLS)\n");
sprintf(mess,
"Could not %s. Unable to calculate checksum (MD5_Final_SLS)\n",
functionType);
LOG(logERROR, (mess));
return FAIL;
}
@@ -370,12 +402,177 @@ int verifyChecksum(char *mess, char *clientChecksum, MD5_CTX *c, char *msg) {
// compare checksum
if (strcmp(clientChecksum, checksum)) {
sprintf(mess,
"Checksum of %s does not match. Client "
"Could not %s. Checksum of %s does not match. Client "
"checksum:%s, copied checksum:%s\n",
msg, clientChecksum, checksum);
functionType, msg, clientChecksum, checksum);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tChecksum verified\n"));
LOG(logINFO, ("\tChecksum of %s verified\n", msg));
return OK;
}
}
int setupDetectorServer(char *mess, char *sname) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
// give permissions
if (snprintf(cmd, MAX_STR_LENGTH, "chmod 777 %s", sname) >=
MAX_STR_LENGTH) {
strcpy(mess, "Could not copy detector server. Command to give "
"permissions to server is too long\n");
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (permissions). %s\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tPermissions modified\n"));
// symbolic link
if (snprintf(cmd, MAX_STR_LENGTH, "ln -sf %s %s", sname,
LINKED_SERVER_NAME) >= MAX_STR_LENGTH) {
strcpy(mess, "Could not copy detector server. Command to "
"create symbolic link too long\n");
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (symbolic link). %s\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tSymbolic link created\n"));
// blackfin boards (respawn) (only kept for backwards compatibility)
#if defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || \
defined(GOTTHARDD)
// delete every line with DetectorServer in /etc/inittab
strcpy(cmd, "sed -i '/DetectorServer/d' /etc/inittab");
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (del respawning). %s\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tinittab: DetectoServer line deleted\n"));
// add new link name to /etc/inittab
if (snprintf(cmd, MAX_STR_LENGTH,
"echo 'ttyS0::respawn:/./%s' >> /etc/inittab",
LINKED_SERVER_NAME) >= MAX_STR_LENGTH) {
strcpy(mess, "Could not copy detector server. Command "
"to add new server for spawning is too long\n");
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (respawning). %s\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tinittab: updated for respawning\n"));
#endif
// sync
strcpy(cmd, "sync");
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (sync). %s\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tsync\n"));
return OK;
}
int writeBinaryFile(char *mess, char *fname, char *buffer,
const uint64_t filesize, char *errorPrefix) {
LOG(logINFO, ("\tWriting Detector Server Binary...\n"));
FILE *fp = fopen(fname, "wb");
if (fp == NULL) {
sprintf(mess,
"Could not %s. (opening file to write(%s). "
"Maybe it is being used? Try another name?\n",
errorPrefix, fname);
LOG(logERROR, (mess));
return FAIL;
}
size_t bytesWritten = 0;
size_t unitSize = 128;
int oldProgress = 0;
while (bytesWritten < filesize) {
// print progress
int progress = (int)(((double)(bytesWritten) / filesize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
// for less than 128 bytes
ssize_t writeSize = unitSize;
if ((unitSize + bytesWritten) > filesize) {
writeSize = filesize - bytesWritten;
}
size_t bytes = fwrite((char *)buffer + bytesWritten, 1, writeSize, fp);
// write
if (bytes != (size_t)writeSize) {
sprintf(mess,
"Could not %s. Expected to write %lu "
"bytes, wrote %lu bytes). No space left? \n",
errorPrefix, (long unsigned int)filesize,
(long unsigned int)bytesWritten);
LOG(logERROR, (mess));
return FAIL;
}
bytesWritten += bytes;
LOG(logDEBUG1,
("bytesWritten:%lu filesize:%lu\n", bytesWritten, filesize));
}
if (fclose(fp) != 0) {
sprintf(mess, "Could not %s. (closing file pointer)\n", errorPrefix);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWritten binary to %s (%lu bytes)\n", fname,
(long unsigned int)bytesWritten));
return OK;
}
int moveBinaryFile(char *mess, char *dest, char *src, char *errorPrefix) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
// one can move into the current process binary (will not interfere in
// kernel mode)
if (snprintf(cmd, MAX_STR_LENGTH, "mv %s %s", src, dest) >=
MAX_STR_LENGTH) {
sprintf(mess, "Could not %s. Command to move binary is too long\n",
errorPrefix);
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH, "Could not %s. (moving). %s\n",
errorPrefix, retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tMoved file from %s to %s\n", src, dest));
return OK;
}

View File

@@ -1,418 +0,0 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "programFpgaBlackfin.h"
#include "clogger.h"
#include "common.h"
#include "sls/ansi.h"
#include "slsDetectorServer_defs.h"
#include <string.h>
#include <sys/sysinfo.h>
#include <unistd.h> // usleep
/* global variables */
// clang-format off
#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s
#define CMD_GET_FLASH "awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd"
#define CMD_FPGA_PICKED_STATUS "cat /sys/class/gpio/gpio7/value"
#define FLASH_BUFFER_MEMORY_SIZE (128 * 1024) // 500 KB
// clang-format on
#define FLASH_DRIVE_NAME_SIZE 16
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0};
int gpioDefined = 0;
extern int executeCommand(char *command, char *result, enum TLogLevel level);
int latestKernelVerified = -1;
#define KERNEL_DATE_VRSN_3GPIO "Fri Oct 29 00:00:00 2021"
void defineGPIOpins() {
#ifdef VIRTUAL
return;
#endif
if (latestKernelVerified == -1) {
if (FAIL == validateKernelVersion(KERNEL_DATE_VRSN_3GPIO)) {
latestKernelVerified = 0;
LOG(logWARNING,
("Kernel too old to use gpio 3 pins. Not the end "
"of the world. Continuing with current kernel.\n"));
} else {
latestKernelVerified = 1;
}
}
if (!gpioDefined) {
// define the gpio pins
system("echo 7 > /sys/class/gpio/export");
LOG(logINFO, ("\tgpio7: defined\n"));
system("echo in > /sys/class/gpio/gpio7/direction");
LOG(logINFO, ("\tgpio7: setting intput\n"));
system("echo 9 > /sys/class/gpio/export");
LOG(logINFO, ("\tgpio9: defined\n"));
if (latestKernelVerified == 1) {
// gpio 3 = not chip enable
system("echo 3 > /sys/class/gpio/export");
LOG(logINFO, ("\tgpio3: defined\n"));
}
gpioDefined = 1;
} else
LOG(logDEBUG1, ("gpio pins already defined earlier\n"));
}
void FPGAdontTouchFlash() {
#ifdef VIRTUAL
return;
#endif
// define as output pins
system("echo out > /sys/class/gpio/gpio9/direction");
LOG(logINFO, ("\tgpio9: setting output\n"));
if (latestKernelVerified == 1) {
// gpio 3 = not chip enable
system("echo out > /sys/class/gpio/gpio3/direction");
LOG(logINFO, ("\tgpio3: setting output\n"));
}
// tell FPGA to not touch flash
system("echo 0 > /sys/class/gpio/gpio9/value");
LOG(logINFO, ("\tgpio9: fpga dont touch flash\n"));
if (latestKernelVerified == 1) {
system("echo 1 > /sys/class/gpio/gpio3/value");
LOG(logINFO, ("\tgpio3: fpga dont touch flash\n"));
}
// usleep(100*1000);
}
void FPGATouchFlash() {
#ifdef VIRTUAL
return;
#endif
// tell FPGA to touch flash to program itself
system("echo in > /sys/class/gpio/gpio9/direction");
LOG(logINFO, ("\tgpio9: setting input\n"));
if (latestKernelVerified == 1) {
system("echo in > /sys/class/gpio/gpio3/direction");
LOG(logINFO, ("\tgpio3: setting input\n"));
}
}
void resetFPGA() {
LOG(logINFOBLUE, ("Reseting FPGA\n"));
#ifdef VIRTUAL
return;
#endif
FPGAdontTouchFlash();
FPGATouchFlash();
usleep(CTRL_SRVR_INIT_TIME_US);
}
int deleteOldFile(char *mess) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
char *format = "rm -fr %s";
if (snprintf(cmd, MAX_STR_LENGTH, format, TEMP_PROG_FILE_NAME) >=
MAX_STR_LENGTH) {
strcpy(
mess,
"Could not program fpga. Command to delete old file is too long\n");
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not delete old file: %s)\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
LOG(logINFO,
("\tDeleted old programming file (%s)\n", TEMP_PROG_FILE_NAME));
return OK;
}
int preparetoCopyFPGAProgram(FILE **fd, uint64_t fsize, char *mess) {
if (deleteOldFile(mess) == FAIL) {
return FAIL;
}
// check available memory to copy program
{
struct sysinfo info;
sysinfo(&info);
if (fsize >= info.freeram) {
sprintf(mess,
"Could not program fpga. Not enough memory to copy "
"program. [File size:%ldMB, free RAM: %ldMB]\n",
(long int)(fsize / (1024 * 1024)),
(long int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
return FAIL;
}
}
// open file to copy program
*fd = fopen(TEMP_PROG_FILE_NAME, "w");
if (*fd == NULL) {
sprintf(mess, "Unable to open %s in write mode\n", TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tGoing to copy program to %s\n", TEMP_PROG_FILE_NAME));
return OK;
}
int copyToFlash(ssize_t fsize, char *clientChecksum, char *mess) {
if (getDrive(mess) == FAIL) {
return FAIL;
}
FILE *flashfd = NULL;
FILE *srcfd = NULL;
if (openFileForFlash(&flashfd, &srcfd, mess) == FAIL) {
return FAIL;
}
if (eraseFlash(mess) == FAIL) {
fclose(flashfd);
fclose(srcfd);
return FAIL;
}
if (writeToFlash(fsize, flashfd, srcfd, mess) == FAIL) {
return FAIL;
}
if (deleteOldFile(mess) == FAIL) {
return FAIL;
}
/* ignoring this until flash fixed
if (verifyChecksumFromFlash(mess, clientChecksum, flashDriveName, fsize) == FAIL) { return FAIL;
}
*/
if (waitForFPGAtoTouchFlash(mess) == FAIL) {
return FAIL;
}
return OK;
}
int getDrive(char *mess) {
#ifdef VIRTUAL
strcpy(flashDriveName, "/tmp/SLS_mtd3");
return OK;
#endif
LOG(logDEBUG1, ("Finding flash drive...\n"));
// getting the drive
// root:/> cat /proc/mtd
// dev: size erasesize name
// mtd0: 00040000 00020000 "bootloader(nor)"
// mtd1: 00100000 00020000 "linux kernel(nor)"
// mtd2: 002c0000 00020000 "file system(nor)"
// mtd3: 01000000 00010000 "bitfile(spi)"
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
strcpy(cmd, CMD_GET_FLASH);
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not get flash drive: %s)\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
char *pch = strtok(retvals, ":");
if (pch == NULL) {
strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n");
LOG(logERROR, (mess));
return FAIL;
}
memset(flashDriveName, 0, sizeof(flashDriveName));
strcpy(flashDriveName, "/dev/");
strcat(flashDriveName, pch);
LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName));
return OK;
}
int openFileForFlash(FILE **flashfd, FILE **srcfd, char *mess) {
FPGAdontTouchFlash();
// open src file
*srcfd = fopen(TEMP_PROG_FILE_NAME, "r");
if (*srcfd == NULL) {
sprintf(mess,
"Could not flash. Unable to open temp program file %s in read "
"mode\n",
TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("Temp file ready for reading\n"));
// open flash drive for writing
*flashfd = fopen(flashDriveName, "w");
if (*flashfd == NULL) {
fclose(*srcfd);
sprintf(mess, "Unable to open flash drive %s in write mode\n",
flashDriveName);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tFlash ready for writing\n"));
return OK;
}
int eraseFlash(char *mess) {
LOG(logINFO, ("\tErasing Flash...\n"));
#ifdef VIRTUAL
return OK;
#endif
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
char *format = "flash_eraseall %s";
if (snprintf(cmd, MAX_STR_LENGTH, format, flashDriveName) >=
MAX_STR_LENGTH) {
strcpy(mess,
"Could not program fpga. Command to erase flash is too long\n");
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not erase flash: %s)\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
LOG(logINFO, ("\tFlash erased\n"));
return OK;
}
int writeToFlash(ssize_t fsize, FILE *flashfd, FILE *srcfd, char *mess) {
LOG(logDEBUG1, ("writing to flash\n"));
char *buffer = malloc(FLASH_BUFFER_MEMORY_SIZE);
if (buffer == NULL) {
fclose(flashfd);
fclose(srcfd);
strcpy(mess, "Could not program fpga. Memory allocation to write to "
"flash failed.\n");
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWriting to Flash...\n"));
int oldProgress = 0;
ssize_t totalBytes = 0;
ssize_t bytes =
fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd);
while (bytes > 0) {
ssize_t bytesWritten =
fwrite((void *)buffer, sizeof(char), bytes, flashfd);
totalBytes += bytesWritten;
if (bytesWritten != bytes) {
free(buffer);
fclose(flashfd);
fclose(srcfd);
sprintf(mess,
"Could not write to flash (bytes written:%ld, expected: "
"%ld, total written:%ld)\n",
(long int)bytesWritten, (long int)bytes,
(long int)totalBytes);
LOG(logERROR, (mess));
return FAIL;
}
// print progress
if (fsize > 0) {
int progress = (int)(((double)(totalBytes) / fsize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
} else
printf(".");
bytes = fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE,
srcfd);
}
if (fsize <= 0) {
printf("\n");
}
free(buffer);
fclose(flashfd);
fclose(srcfd);
LOG(logINFO, ("\tWrote %ld bytes to flash\n", totalBytes));
if (totalBytes != fsize) {
sprintf(mess,
"Could not program fpga. Incorrect bytes written to flash %lu "
"[expected: %lu]\n",
totalBytes, fsize);
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int waitForFPGAtoTouchFlash(char *mess) {
// touch and program
FPGATouchFlash();
#ifdef VIRTUAL
return OK;
#endif
LOG(logINFO, ("\tWaiting for FPGA to program from flash\n"));
int timeSpent = 0;
int result = 0;
while (result == 0) {
// time taken for fpga to pick up from flash
usleep(1000);
timeSpent += 1000;
if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) {
sprintf(
mess,
"Could not program fpga. (exceeded max time allowed: %ds)\n",
MAX_TIME_FPGA_TOUCH_FLASH_US / (1000 * 1000));
LOG(logERROR, (mess));
return FAIL;
}
// read gpio status
char retvals[MAX_STR_LENGTH] = {0};
if (FAIL ==
executeCommand(CMD_FPGA_PICKED_STATUS, retvals, logDEBUG1)) {
snprintf(
mess, MAX_STR_LENGTH,
"Could not program fpga. (could not read gpio status: %s)\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
// convert to int
if (sscanf(retvals, "%d\n", &result) != 1) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not scan int for gpio "
"status: [%s])\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("gpi07 returned %d\n", result));
}
LOG(logINFO, ("\tFPGA has picked up the program from flash\n"));
return OK;
}

View File

@@ -0,0 +1,574 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "programViaBlackfin.h"
#include "clogger.h"
#include "common.h"
#include "sls/ansi.h"
#include "slsDetectorServer_defs.h"
#include <string.h>
#include <sys/sysinfo.h>
#include <unistd.h> // usleep
/* global variables */
// clang-format off
#define MAX_TIME_FPGA_TOUCH_FLASH_US (10 * 1000 * 1000) // 10s
#define CMD_GPIO7_DEFINE "echo 7 > /sys/class/gpio/export"
#define CMD_GPIO9_DEFINE "echo 9 > /sys/class/gpio/export"
#define CMD_GPIO3_DEFINE "echo 3 > /sys/class/gpio/export"
#define CMD_GPIO7_EXIST "/sys/class/gpio/gpio7"
#define CMD_GPIO9_EXIST "/sys/class/gpio/gpio9"
#define CMD_GPIO3_EXIST "/sys/class/gpio/gpio3"
#define CMD_GPIO9_DEFINE_OUT "echo out > /sys/class/gpio/gpio9/direction"
#define CMD_GPIO3_DEFINE_OUT "echo out > /sys/class/gpio/gpio3/direction"
#define CMD_GPIO7_DEFINE_IN "echo in > /sys/class/gpio/gpio7/direction"
#define CMD_GPIO9_DEFINE_IN "echo in > /sys/class/gpio/gpio9/direction"
#define CMD_GPIO3_DEFINE_IN "echo in > /sys/class/gpio/gpio3/direction"
#define CMD_GPIO9_DONT_TOUCH_FLASH "echo 0 > /sys/class/gpio/gpio9/value"
#define CMD_GPIO3_DONT_TOUCH_FLASH "echo 0 > /sys/class/gpio/gpio3/value"
#define CMD_FPGA_PICKED_STATUS "cat /sys/class/gpio/gpio7/value"
#define CMD_GET_FPGA_FLASH_DRIVE "awk \'$4== \"\\\"bitfile(spi)\\\"\" {print $1}\' /proc/mtd"
#define CMD_GET_KERNEL_FLASH_DRIVE "awk \'$4== \"\\\"linux\" {print $1}\' /proc/mtd"
#define FLASH_BUFFER_MEMORY_SIZE (128 * 1024) // 500 KB
// clang-format on
#define FLASH_DRIVE_NAME_SIZE 16
#ifdef VIRTUAL
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = "/tmp/SLS_mtd3";
#else
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0};
#endif
char messageType[SHORT_STR_LENGTH] = {0};
extern int executeCommand(char *command, char *result, enum TLogLevel level);
int latestKernelVerified = -1;
#define KERNEL_DATE_VRSN_3GPIO "Fri Oct 29 00:00:00 2021"
int defineGPIOpins(char *mess) {
#ifdef VIRTUAL
return OK;
#endif
// only latest kernel can use gpio3 pins
if (latestKernelVerified == -1) {
if (FAIL == validateKernelVersion(KERNEL_DATE_VRSN_3GPIO)) {
latestKernelVerified = 0;
LOG(logWARNING,
("Kernel too old to use gpio 3 pins. Update kernel to "
"guarantee error-free fpga programming. \n\tNot the end "
"of the world. Continuing with current kernel...\n"));
} else {
latestKernelVerified = 1;
}
}
char retvals[MAX_STR_LENGTH] = {0};
// define gpio7
if (access(CMD_GPIO7_EXIST, F_OK) != 0) {
if (executeCommand(CMD_GPIO7_DEFINE, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not define gpio7 pins for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio7: defined\n"));
} else {
LOG(logINFO, ("\tgpio7: already defined\n"));
}
// define gpio7 direction
if (executeCommand(CMD_GPIO7_DEFINE_IN, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio7 as input for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio7: setting intput\n"));
// define gpio9
if (access(CMD_GPIO9_EXIST, F_OK) != 0) {
if (executeCommand(CMD_GPIO9_DEFINE, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not define gpio9 pins for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio9: defined\n"));
} else {
LOG(logINFO, ("\tgpio9: already defined\n"));
}
// define gpio3 (not chip enable)
if (latestKernelVerified == 1) {
if (access(CMD_GPIO3_EXIST, F_OK) != 0) {
if (executeCommand(CMD_GPIO3_DEFINE, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not define gpio3 pins for fpga (%s)\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio3: defined\n"));
} else {
LOG(logINFO, ("\tgpio3: already defined\n"));
}
}
return OK;
}
int FPGAdontTouchFlash(char *mess) {
#ifdef VIRTUAL
return OK;
#endif
char retvals[MAX_STR_LENGTH] = {0};
// define gpio9 as output
if (executeCommand(CMD_GPIO9_DEFINE_OUT, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio9 as output for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio9: setting output\n"));
// define gpio3 as output
if (latestKernelVerified == 1) {
if (executeCommand(CMD_GPIO3_DEFINE_OUT, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio3 as output for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio3: setting output\n"));
}
// tell FPGA to not: gpio9
if (executeCommand(CMD_GPIO9_DONT_TOUCH_FLASH, retvals, logDEBUG1) ==
FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio9 to not touch flash for fpga (%s)\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio9: fpga dont touch flash\n"));
// tell FPGA to not: gpio3
if (latestKernelVerified == 1) {
if (executeCommand(CMD_GPIO3_DONT_TOUCH_FLASH, retvals, logDEBUG1) ==
FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio3 to not touch flash for fpga (%s)\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio3: fpga dont touch flash\n"));
}
// usleep(100*1000);
return OK;
}
int FPGATouchFlash(char *mess) {
#ifdef VIRTUAL
return OK;
#endif
char retvals[MAX_STR_LENGTH] = {0};
// tell FPGA to touch flash to program itself
if (executeCommand(CMD_GPIO9_DEFINE_IN, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio9 as input for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio9: setting input\n"));
if (latestKernelVerified == 1) {
if (executeCommand(CMD_GPIO3_DEFINE_IN, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not set gpio3 as input for fpga (%s)\n", retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tgpio3: setting input\n"));
}
return OK;
}
int resetFPGA(char *mess) {
LOG(logINFOBLUE, ("Reseting FPGA\n"));
#ifdef VIRTUAL
return OK;
#endif
if (FPGAdontTouchFlash(mess) == FAIL) {
return FAIL;
}
if (FPGATouchFlash(mess) == FAIL) {
return FAIL;
}
usleep(CTRL_SRVR_INIT_TIME_US);
return OK;
}
int emptyTempFolder(char *mess) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
if (snprintf(cmd, MAX_STR_LENGTH, "rm -fr %s",
TEMP_PROG_FOLDER_NAME_ALL_FILES) >= MAX_STR_LENGTH) {
sprintf(mess,
"Could not update %s. Command to empty %s folder is too long\n",
messageType, TEMP_PROG_FOLDER_NAME);
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not update %s. (could not empty %s folder: %s)\n",
messageType, TEMP_PROG_FOLDER_NAME, retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tEmptied temp folder(%s)\n", TEMP_PROG_FOLDER_NAME));
return OK;
}
int preparetoCopyProgram(char *mess, char *functionType, FILE **fd,
uint64_t fsize) {
if (emptyTempFolder(mess) == FAIL) {
return FAIL;
}
// check available memory to copy program
{
struct sysinfo info;
sysinfo(&info);
if (fsize >= info.freeram) {
sprintf(mess,
"Could not %s. Not enough memory to copy "
"program. [File size:%ldMB, free RAM: %ldMB]\n",
functionType, (long int)(fsize / (1024 * 1024)),
(long int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
return FAIL;
}
}
// open file to copy program
*fd = fopen(TEMP_PROG_FILE_NAME, "w");
if (*fd == NULL) {
sprintf(mess, "Could not %s. Unable to open %s in write mode\n",
functionType, TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tGoing to copy program to %s\n", TEMP_PROG_FILE_NAME));
return OK;
}
int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index,
char *functionType, char *clientChecksum,
ssize_t fsize) {
memset(messageType, 0, sizeof(messageType));
strcpy(messageType, functionType);
if (getDrive(mess, index) == FAIL) {
return FAIL;
}
FILE *flashfd = NULL;
FILE *srcfd = NULL;
if (openFileForFlash(mess, &flashfd, &srcfd) == FAIL) {
return FAIL;
}
if (index == PROGRAM_FPGA) {
if (FPGAdontTouchFlash(mess) == FAIL) {
return FAIL;
}
}
if (eraseFlash(mess) == FAIL) {
fclose(flashfd);
fclose(srcfd);
return FAIL;
}
if (writeToFlash(mess, fsize, flashfd, srcfd) == FAIL) {
return FAIL;
}
if (emptyTempFolder(mess) == FAIL) {
return FAIL;
}
/* remove condition when flash fpga fixed */
if (index == PROGRAM_KERNEL) {
if (verifyChecksumFromFlash(mess, messageType, clientChecksum,
flashDriveName, fsize) == FAIL) {
return FAIL;
}
}
if (index == PROGRAM_FPGA) {
if (waitForFPGAtoTouchFlash(mess) == FAIL) {
return FAIL;
}
}
// kernel
else {
char retvals[MAX_STR_LENGTH] = {0};
if (executeCommand("sync", retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not update %s. (could not sync)\n", messageType);
LOG(logERROR, (mess));
return FAIL;
}
}
return OK;
}
int getDrive(char *mess, enum PROGRAM_INDEX index) {
#ifdef VIRTUAL
return OK;
#endif
LOG(logDEBUG1, ("Finding flash drive...\n"));
// getting the drive
// root:/> cat /proc/mtd
// dev: size erasesize name
// mtd0: 00040000 00020000 "bootloader(nor)"
// mtd1: 00100000 00020000 "linux kernel(nor)"
// mtd2: 002c0000 00020000 "file system(nor)"
// mtd3: 01000000 00010000 "bitfile(spi)"
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
if (index == PROGRAM_FPGA) {
strcpy(cmd, CMD_GET_FPGA_FLASH_DRIVE);
} else {
strcpy(cmd, CMD_GET_KERNEL_FLASH_DRIVE);
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not %s. (could not get flash drive: %s)\n", messageType,
retvals);
LOG(logERROR, (mess));
return FAIL;
}
if (strlen(retvals) == 0) {
LOG(logERROR, ("Could not %s. Could not get mtd drive, script returned "
"empty string\n",
messageType));
return FAIL;
}
char *pch = strtok(retvals, ":");
if (pch == NULL) {
sprintf(mess,
"Could not %s. Could not get mtd drive to flash (strtok "
"fail).\n",
messageType);
LOG(logERROR, (mess));
return FAIL;
}
memset(flashDriveName, 0, sizeof(flashDriveName));
sprintf(flashDriveName, "/dev/%s", pch);
LOG(logINFO, ("\tFlash drive found: %s\n", flashDriveName));
return OK;
}
int openFileForFlash(char *mess, FILE **flashfd, FILE **srcfd) {
// open src file
*srcfd = fopen(TEMP_PROG_FILE_NAME, "r");
if (*srcfd == NULL) {
sprintf(mess,
"Could not %s. Unable to open temp program file %s in read "
"mode\n",
messageType, TEMP_PROG_FILE_NAME);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("Temp file ready for reading\n"));
// open flash drive for writing
*flashfd = fopen(flashDriveName, "w");
if (*flashfd == NULL) {
fclose(*srcfd);
sprintf(mess,
"Could not %s. Unable to open flash drive %s in write "
"mode\n",
messageType, flashDriveName);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tFlash ready for writing\n"));
return OK;
}
int eraseFlash(char *mess) {
LOG(logINFO, ("\tErasing Flash...\n"));
#ifdef VIRTUAL
return OK;
#endif
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
if (snprintf(cmd, MAX_STR_LENGTH, "flash_eraseall %s", flashDriveName) >=
MAX_STR_LENGTH) {
sprintf(mess, "Could not %s. Command to erase flash is too long\n",
messageType);
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not update %s. (could not erase flash: %s)\n",
messageType, retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tFlash erased\n"));
return OK;
}
int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, FILE *srcfd) {
LOG(logDEBUG1, ("writing to flash\n"));
char *buffer = malloc(FLASH_BUFFER_MEMORY_SIZE);
if (buffer == NULL) {
fclose(flashfd);
fclose(srcfd);
sprintf(mess,
"Could not %s. Memory allocation to write to "
"flash failed.\n",
messageType);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWriting to Flash...\n"));
int oldProgress = 0;
ssize_t totalBytes = 0;
ssize_t bytes =
fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE, srcfd);
while (bytes > 0) {
ssize_t bytesWritten =
fwrite((void *)buffer, sizeof(char), bytes, flashfd);
totalBytes += bytesWritten;
if (bytesWritten != bytes) {
free(buffer);
fclose(flashfd);
fclose(srcfd);
sprintf(mess,
"Could not %s. Could not write to flash (bytes "
"written:%ld, expected: "
"%ld, total written:%ld)\n",
messageType, (long int)bytesWritten, (long int)bytes,
(long int)totalBytes);
LOG(logERROR, (mess));
return FAIL;
}
// print progress
if (fsize > 0) {
int progress = (int)(((double)(totalBytes) / fsize) * 100);
if (oldProgress != progress) {
printf("%d%%\r", progress);
fflush(stdout);
oldProgress = progress;
}
} else
printf(".");
bytes = fread((void *)buffer, sizeof(char), FLASH_BUFFER_MEMORY_SIZE,
srcfd);
}
if (fsize <= 0) {
printf("\n");
}
free(buffer);
fclose(flashfd);
fclose(srcfd);
LOG(logINFO, ("\tWrote %ld bytes to flash\n", totalBytes));
if (totalBytes != fsize) {
sprintf(mess,
"Could not %s. Incorrect bytes written to flash %lu "
"[expected: %lu]\n",
messageType, totalBytes, fsize);
LOG(logERROR, (mess));
return FAIL;
}
return OK;
}
int waitForFPGAtoTouchFlash(char *mess) {
// touch and program
if (FPGATouchFlash(mess) == FAIL) {
return FAIL;
}
#ifdef VIRTUAL
return OK;
#endif
LOG(logINFO, ("\tWaiting for FPGA to program from flash\n"));
int timeSpent = 0;
int result = 0;
while (result == 0) {
// time taken for fpga to pick up from flash
usleep(1000);
timeSpent += 1000;
if (timeSpent >= MAX_TIME_FPGA_TOUCH_FLASH_US) {
sprintf(
mess,
"Could not program fpga. (exceeded max time allowed: %ds)\n",
MAX_TIME_FPGA_TOUCH_FLASH_US / (1000 * 1000));
LOG(logERROR, (mess));
return FAIL;
}
// read gpio status
char retvals[MAX_STR_LENGTH] = {0};
if (FAIL ==
executeCommand(CMD_FPGA_PICKED_STATUS, retvals, logDEBUG1)) {
snprintf(
mess, MAX_STR_LENGTH,
"Could not program fpga. (could not read gpio status: %s)\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
// convert to int
if (sscanf(retvals, "%d\n", &result) != 1) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not scan int for gpio "
"status: [%s])\n",
retvals);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logDEBUG1, ("gpi07 returned %d\n", result));
}
LOG(logINFO, ("\tFPGA has picked up the program from flash\n"));
return OK;
}

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
#include "programFpgaNios.h"
#include "programViaNios.h"
#include "clogger.h"
#include "common.h"
#include "sls/ansi.h"
@@ -11,10 +11,19 @@
/* global variables */
#define CMD_GET_FLASH "awk \'$5== \"Application\" {print $1}\' /proc/mtd"
#define CMD_GET_FPGA_FLASH_DRIVE \
"awk \'$5== \"Application\" {print $1}\' /proc/mtd"
#define CMD_GET_KERNEL_FLASH_DRIVE \
"awk \'$5== \"Linux\" && $9 != \"Backup\\\"\" {print $1}\' /proc/mtd"
#define FLASH_DRIVE_NAME_SIZE 16
#ifdef VIRTUAL
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = "/tmp/SLS_mtd3";
#else
char flashDriveName[FLASH_DRIVE_NAME_SIZE] = {0};
#endif
char messageType[SHORT_STR_LENGTH] = {0};
#define MICROCONTROLLER_FILE "/dev/ttyAL0"
extern int executeCommand(char *command, char *result, enum TLogLevel level);
@@ -35,19 +44,19 @@ void rebootControllerAndFPGA() {
system(command);
}
int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc,
int eraseAndWriteToFlash(char *mess, enum PROGRAM_INDEX index,
char *functionType, char *checksum, char *fpgasrc,
uint64_t fsize) {
if (verifyChecksumFromBuffer(mess, checksum, fpgasrc, fsize) == FAIL) {
return FAIL;
}
memset(messageType, 0, sizeof(messageType));
strcpy(messageType, functionType);
if (getDrive(mess) == FAIL) {
if (getDrive(mess, index) == FAIL) {
return FAIL;
}
FILE *flashfd = NULL;
if (openFileForFlash(&flashfd, mess) == FAIL) {
if (openFileForFlash(mess, &flashfd) == FAIL) {
return FAIL;
}
@@ -56,21 +65,33 @@ int eraseAndWriteToFlash(char *mess, char *checksum, char *fpgasrc,
return FAIL;
}
if (writeToFlash(fsize, flashfd, fpgasrc, mess) == FAIL) {
if (writeToFlash(mess, fsize, flashfd, fpgasrc) == FAIL) {
return FAIL;
}
/* ignoring this until a consistent way to read from nios flash
if (verifyChecksumFromFlash(mess, checksum, flashDriveName, fsize) ==
FAIL) {
return FAIL;
/* remove condition when flash fpga fixed */
if (index == PROGRAM_KERNEL) {
if (verifyChecksumFromFlash(mess, messageType, checksum, flashDriveName,
fsize) == FAIL) {
return FAIL;
}
}
*/
if (index == PROGRAM_KERNEL) {
char retvals[MAX_STR_LENGTH] = {0};
if (executeCommand("sync", retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not update %s. (could not sync)\n", messageType);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
}
return OK;
}
int getDrive(char *mess) {
int getDrive(char *mess, enum PROGRAM_INDEX index) {
#ifdef VIRTUAL
strcpy(flashDriveName, "/tmp/SLS_mtd3");
return OK;
#endif
LOG(logDEBUG1, ("Finding flash drive...\n"));
@@ -86,18 +107,33 @@ int getDrive(char *mess) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
strcpy(cmd, CMD_GET_FLASH);
if (index == PROGRAM_FPGA) {
strcpy(cmd, CMD_GET_FPGA_FLASH_DRIVE);
} else {
strcpy(cmd, CMD_GET_KERNEL_FLASH_DRIVE);
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not get flash drive: %s)\n",
"Could not %s. (could not get flash drive: %s)\n", messageType,
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
}
if (strlen(retvals) == 0) {
LOG(logERROR, ("Could not %s. Could not get mtd drive, script returned "
"empty string\n",
messageType));
return FAIL;
}
char *pch = strtok(retvals, ":");
if (pch == NULL) {
strcpy(mess, "Could not get mtd drive to flash (strtok fail).\n");
sprintf(
mess,
"Could not %s. Could not get mtd drive to flash (strtok fail).\n",
messageType);
LOG(logERROR, (mess));
return FAIL;
}
@@ -109,11 +145,12 @@ int getDrive(char *mess) {
return OK;
}
int openFileForFlash(FILE **flashfd, char *mess) {
int openFileForFlash(char *mess, FILE **flashfd) {
*flashfd = fopen(flashDriveName, "w");
if (*flashfd == NULL) {
sprintf(mess, "Unable to open flash drive %s in write mode\n",
flashDriveName);
sprintf(mess,
"Could not %s. Unable to open flash drive %s in write mode\n",
messageType, flashDriveName);
LOG(logERROR, (mess));
return FAIL;
}
@@ -130,17 +167,16 @@ int eraseFlash(char *mess) {
char cmd[MAX_STR_LENGTH] = {0};
char retvals[MAX_STR_LENGTH] = {0};
char *format = "flash_erase %s 0 0";
if (snprintf(cmd, MAX_STR_LENGTH, format, flashDriveName) >=
if (snprintf(cmd, MAX_STR_LENGTH, "flash_erase %s 0 0", flashDriveName) >=
MAX_STR_LENGTH) {
strcpy(mess,
"Could not program fpga. Command to erase flash is too long\n");
sprintf(mess, "Could not %s. Command to erase flash is too long\n",
messageType);
LOG(logERROR, (mess));
return FAIL;
}
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not program fpga. (could not erase flash: %s)\n",
"Could not %s. (could not erase flash: %s)\n", messageType,
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
return FAIL;
@@ -150,19 +186,20 @@ int eraseFlash(char *mess) {
return OK;
}
int writeToFlash(ssize_t fsize, FILE *flashfd, char *buffer, char *mess) {
int writeToFlash(char *mess, ssize_t fsize, FILE *flashfd, char *buffer) {
LOG(logINFO, ("\tWriting to Flash...\n"));
ssize_t bytesWritten = fwrite((void *)buffer, sizeof(char), fsize, flashfd);
if (bytesWritten != fsize) {
fclose(flashfd);
sprintf(mess,
"Could not program fpga. Incorrect bytes written to flash %lu "
"Could not %s. Incorrect bytes written to flash %lu "
"[expected: %lu]\n",
(long int)bytesWritten, (long int)fsize);
messageType, (long int)bytesWritten, (long int)fsize);
LOG(logERROR, (mess));
return FAIL;
}
LOG(logINFO, ("\tWritten to Flash\n"));
fclose(flashfd);
LOG(logINFO, ("\tWrote %ld bytes to flash\n", bytesWritten));
return OK;
}

View File

@@ -92,14 +92,13 @@ void init_detector() {
#ifdef EIGERD
udpDetails[0].dstport2 = DEFAULT_UDP_DST_PORTNO + 1;
#endif
lockStatus = 0;
if (isControlServer) {
basictests();
initControlServer();
} else
} else {
initStopServer();
strcpy(mess, "dummy message");
lockStatus = 0;
}
}
int decode_function(int file_des) {
@@ -415,6 +414,8 @@ void function_table() {
flist[F_GET_READOUT_SPEED] = &get_readout_speed;
flist[F_SET_READOUT_SPEED] = &set_readout_speed;
flist[F_GET_KERNEL_VERSION] = &get_kernel_version;
flist[F_UPDATE_KERNEL] = &update_kernel;
flist[F_UPDATE_DETECTOR_SERVER] = &update_detector_server;
// check
if (NUM_DET_FUNCTIONS >= RECEIVER_ENUM_START) {
@@ -472,7 +473,7 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
if (strlen(result)) {
if (success) {
success = FAIL;
LOG(logERROR, ("%s\n", result));
LOG(logERROR, ("Executing cmd[%s]:%s\n", cmd, result));
} else {
LOG(level, ("Result:\n[%s]\n", result));
}
@@ -486,11 +487,6 @@ int M_nofunc(int file_des) {
ret = FAIL;
memset(mess, 0, sizeof(mess));
// to receive any arguments
int n = 1;
while (n > 0)
n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER);
sprintf(mess, "Unrecognized Function enum %d. Please do not proceed.\n",
fnum);
LOG(logERROR, (mess));
@@ -1561,15 +1557,8 @@ int set_module(int file_des) {
}
}
// receive all arguments
if (ret == FAIL) {
int n = 1;
while (n > 0)
n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER);
}
// only set
else if (Server_VerifyLock() == OK) {
if (ret == OK && Server_VerifyLock() == OK) {
// check index
// setsettings
@@ -3641,149 +3630,10 @@ int program_fpga(int file_des) {
memset(mess, 0, sizeof(mess));
#if defined(EIGERD) || defined(GOTTHARDD)
// to receive any arguments
int n = 1;
while (n > 0)
n = receiveData(file_des, mess, MAX_STR_LENGTH, OTHER);
functionNotImplemented();
return Server_SendResult(file_des, INT32, NULL, 0);
#else
// only set
if (Server_VerifyLock() == OK) {
LOG(logINFOBLUE, ("Programming FPGA...\n"));
// filesize
uint64_t filesize = 0;
if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0)
return printSocketReadError();
LOG(logDEBUG1, ("Program size is: %lld\n", (long long int)filesize));
// checksum
char checksum[MAX_STR_LENGTH];
memset(checksum, 0, MAX_STR_LENGTH);
if (receiveData(file_des, checksum, MAX_STR_LENGTH, OTHER) < 0)
return printSocketReadError();
LOG(logDEBUG1, ("checksum is: %s\n\n", checksum));
#if defined(MYTHEN3D) || defined(GOTTHARD2D)
if (filesize > NIOS_MAX_APP_IMAGE_SIZE) {
ret = FAIL;
sprintf(mess,
"Could not start programming FPGA. File size 0x%llx "
"exceeds max size 0x%llx. Forgot Compression?\n",
(long long unsigned int)filesize,
(long long unsigned int)NIOS_MAX_APP_IMAGE_SIZE);
LOG(logERROR, (mess));
}
Server_SendResult(file_des, INT32, NULL, 0);
// receive program
if (ret == OK) {
char *fpgasrc = malloc(filesize);
if (receiveData(file_des, fpgasrc, filesize, OTHER) < 0) {
free(fpgasrc);
return printSocketReadError();
}
ret = eraseAndWriteToFlash(mess, checksum, fpgasrc, filesize);
Server_SendResult(file_des, INT32, NULL, 0);
free(fpgasrc);
}
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
return FAIL;
}
#else // jungfrau, ctb, moench
// open file and allocate memory for part program
FILE *fd = NULL;
ret = preparetoCopyFPGAProgram(&fd, filesize, mess);
char *src = NULL;
if (ret == OK) {
src = malloc(MAX_FPGAPROGRAMSIZE);
if (src == NULL) {
fclose(fd);
struct sysinfo info;
sysinfo(&info);
sprintf(mess,
"Could not allocate memory to get fpga program. Free "
"space: %d MB\n",
(int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
ret = FAIL;
}
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL1!\n"));
return FAIL;
}
// copying program part by part
uint64_t totalsize = filesize;
while (ret == OK && filesize) {
uint64_t unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
if (unitprogramsize > filesize) // less than 2mb
unitprogramsize = filesize;
LOG(logDEBUG1, ("unit size to receive is:%lld [filesize:%lld]\n",
(long long unsigned int)unitprogramsize,
(long long unsigned int)filesize));
// receive part of program
if (receiveData(file_des, src, unitprogramsize, OTHER) < 0) {
printSocketReadError();
break;
}
if (unitprogramsize - filesize == 0) {
// src[unitprogramsize] = '\0';
filesize -= unitprogramsize;
// unitprogramsize++;
} else
filesize -= unitprogramsize;
// copy program
if (fwrite((void *)src, sizeof(char), unitprogramsize, fd) !=
unitprogramsize) {
ret = FAIL;
sprintf(mess, "Could not copy program to /var/tmp (size:%ld)\n",
(long int)unitprogramsize);
LOG(logERROR, (mess));
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
break;
}
// print progress
LOG(logINFO,
("\t%d%%\r",
(int)(((double)(totalsize - filesize) / totalsize) * 100)));
fflush(stdout);
}
free(src);
fclose(fd);
// checksum of copied program
if (ret == OK) {
ret = verifyChecksumFromFile(mess, checksum, TEMP_PROG_FILE_NAME);
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
return FAIL;
}
// copy to flash
ret = copyToFlash(totalsize, checksum, mess);
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
LOG(logERROR, ("Program FPGA FAIL!\n"));
return FAIL;
}
#endif // end of Blackfin programming
LOG(logINFOGREEN, ("Programming FPGA completed successfully\n"));
}
receive_program(file_des, PROGRAM_FPGA);
#endif
return ret;
}
@@ -3801,9 +3651,25 @@ int reset_fpga(int file_des) {
if (Server_VerifyLock() == OK) {
if (isControlServer) {
basictests(); // mapping of control server at least
initControlServer();
} else
char *message = NULL;
if (getInitResult(&message) == FAIL) {
ret = FAIL;
strcpy(mess, message);
LOG(logERROR, (mess));
} else {
initControlServer();
}
} else {
initStopServer(); // remapping of stop server
}
if (ret == OK) {
char *message = NULL;
if (getInitResult(&message) == FAIL) {
ret = FAIL;
strcpy(mess, message);
LOG(logERROR, (mess));
}
}
}
#endif
return Server_SendResult(file_des, INT32, NULL, 0);
@@ -4228,9 +4094,8 @@ int copy_detector_server(int file_des) {
char cmd[MAX_STR_LENGTH] = {0};
// tftp server
char *format = "tftp %s -r %s -g";
if (snprintf(cmd, MAX_STR_LENGTH, format, hostname, sname) >=
MAX_STR_LENGTH) {
if (snprintf(cmd, MAX_STR_LENGTH, "tftp %s -r %s -g", hostname,
sname) >= MAX_STR_LENGTH) {
ret = FAIL;
strcpy(mess, "Could not copy detector server. Command to copy "
"server too long\n");
@@ -4244,95 +4109,8 @@ int copy_detector_server(int file_des) {
LOG(logINFO, ("\tServer copied\n"));
}
// give permissions
if (ret == OK) {
if (snprintf(cmd, MAX_STR_LENGTH, "chmod 777 %s", sname) >=
MAX_STR_LENGTH) {
ret = FAIL;
strcpy(mess, "Could not copy detector server. Command to give "
"permissions to server is too long\n");
LOG(logERROR, (mess));
} else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
ret = FAIL;
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (permissions). %s\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
} else {
LOG(logINFO, ("\tPermissions modified\n"));
}
}
// symbolic link
if (ret == OK) {
if (snprintf(cmd, MAX_STR_LENGTH, "ln -sf %s %s", sname,
LINKED_SERVER_NAME) >= MAX_STR_LENGTH) {
ret = FAIL;
strcpy(mess, "Could not copy detector server. Command to "
"create symbolic link too long\n");
LOG(logERROR, (mess));
} else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
ret = FAIL;
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (symbolic link). %s\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
} else {
LOG(logINFO, ("\tSymbolic link created\n"));
}
}
// blackfin boards (respawn) (only kept for backwards compatibility)
#if defined(JUNGFRAUD) || defined(CHIPTESTBOARDD) || defined(MOENCHD) || \
defined(GOTTHARDD)
// delete every line with DetectorServer in /etc/inittab
if (ret == OK) {
strcpy(cmd, "sed -i '/DetectorServer/d' /etc/inittab");
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
ret = FAIL;
snprintf(
mess, MAX_STR_LENGTH,
"Could not copy detector server (del respawning). %s\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
} else {
LOG(logINFO, ("\tinittab: DetectoServer line deleted\n"));
}
}
// add new link name to /etc/inittab
if (ret == OK) {
format = "echo 'ttyS0::respawn:/./%s' >> /etc/inittab";
if (snprintf(cmd, MAX_STR_LENGTH, format, LINKED_SERVER_NAME) >=
MAX_STR_LENGTH) {
ret = FAIL;
strcpy(mess, "Could not copy detector server. Command "
"to add new server for spawning is too long\n");
LOG(logERROR, (mess));
} else if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
ret = FAIL;
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (respawning). %s\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
} else {
LOG(logINFO, ("\tinittab: updated for respawning\n"));
}
}
#endif
// sync
if (ret == OK) {
strcpy(cmd, "sync");
if (executeCommand(cmd, retvals, logDEBUG1) == FAIL) {
ret = FAIL;
snprintf(mess, MAX_STR_LENGTH,
"Could not copy detector server (sync). %s\n",
retvals);
// LOG(logERROR, (mess)); already printed in executecommand
} else {
LOG(logINFO, ("\tsync\n"));
}
ret = setupDetectorServer(mess, sname);
}
}
#endif
@@ -9426,11 +9204,302 @@ int get_kernel_version(int file_des) {
// get only
ret = getKernelVersion(retvals);
if (ret == FAIL) {
snprintf(mess, MAX_STR_LENGTH,
"Could not get kernel version. %s\n", retvals);
if (snprintf(mess, MAX_STR_LENGTH, "Could not get kernel version. %s\n",
retvals) >= MAX_STR_LENGTH) {
ret = FAIL;
strcpy(mess, "Could not get kernel version. Reason too long to copy\n");
}
LOG(logERROR, (mess));
} else {
LOG(logDEBUG1, ("kernel version: [%s]\n", retvals));
}
return Server_SendResult(file_des, OTHER, retvals, sizeof(retvals));
}
int update_kernel(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
#ifdef EIGERD
functionNotImplemented();
return Server_SendResult(file_des, INT32, NULL, 0);
#else
receive_program(file_des, PROGRAM_KERNEL);
#endif
return ret;
}
int update_detector_server(int file_des) {
ret = OK;
memset(mess, 0, sizeof(mess));
return receive_program(file_des, PROGRAM_SERVER);
}
int receive_program(int file_des, enum PROGRAM_INDEX index) {
// only set
if (Server_VerifyLock() == OK) {
char functionType[SHORT_STR_LENGTH] = {0};
switch (index) {
case PROGRAM_FPGA:
strcpy(functionType, "Update Firmware");
break;
case PROGRAM_KERNEL:
strcpy(functionType, "Update Kernel");
break;
case PROGRAM_SERVER:
strcpy(functionType, "Update Server");
break;
}
LOG(logINFOBLUE, ("%s ...\n", functionType));
// filesize
uint64_t filesize = 0;
if (receiveData(file_des, &filesize, sizeof(filesize), INT64) < 0)
return printSocketReadError();
LOG(logINFO, ("\tProgram size: %lld\n", (long long int)filesize));
// client checksum
char checksum[MAX_STR_LENGTH] = {0};
if (receiveData(file_des, checksum, MAX_STR_LENGTH, OTHER) < 0)
return printSocketReadError();
LOG(logINFO, ("\tChecksum: %s\n", checksum));
// server name
char serverName[MAX_STR_LENGTH] = {0};
if (index == PROGRAM_SERVER) {
if (receiveData(file_des, serverName, MAX_STR_LENGTH, OTHER) < 0)
return printSocketReadError();
LOG(logINFO, ("\tServer Name: %s\n", serverName));
}
#if defined(GOTTHARD2D) || defined(MYTHEN3D) || defined(EIGERD)
receive_program_default(file_des, index, functionType, filesize,
checksum, serverName);
#else
receive_program_via_blackfin(file_des, index, functionType, filesize,
checksum, serverName);
#endif
if (ret == OK) {
LOG(logINFOGREEN, ("%s completed successfully\n", functionType));
} else {
LOG(logERROR, ("%s FAIL!\n", functionType));
}
}
return ret;
}
void receive_program_via_blackfin(int file_des, enum PROGRAM_INDEX index,
char *functionType, uint64_t filesize,
char *checksum, char *serverName) {
#if !defined(JUNGFRAUD) && !defined(CHIPTESTBOARDD) && !defined(MOENCHD) && \
!defined(GOTTHARDD)
ret = FAIL;
sprintf(mess,
"Could not %s. program via blackfin not implmented for this "
"detector.\n",
functionType);
LOG(logERROR, (mess));
#else
// open file and allocate memory for part program
FILE *fd = NULL;
ret = preparetoCopyProgram(mess, functionType, &fd, filesize);
char *src = NULL;
if (ret == OK) {
src = malloc(MAX_BLACKFIN_PROGRAM_SIZE);
if (src == NULL) {
fclose(fd);
struct sysinfo info;
sysinfo(&info);
sprintf(mess,
"Could not %s. Memory allocation failure. Free "
"space: %d MB\n",
functionType, (int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
ret = FAIL;
}
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
return;
}
// copying program part by part
uint64_t totalsize = filesize;
while (ret == OK && filesize) {
uint64_t unitprogramsize = MAX_BLACKFIN_PROGRAM_SIZE;
if (unitprogramsize > filesize)
unitprogramsize = filesize;
LOG(logDEBUG1, ("unit size to receive is:%lld [filesize:%lld]\n",
(long long unsigned int)unitprogramsize,
(long long unsigned int)filesize));
// receive part of program
if (receiveData(file_des, src, unitprogramsize, OTHER) < 0) {
printSocketReadError();
break;
}
filesize -= unitprogramsize;
// copy program
if (fwrite((void *)src, sizeof(char), unitprogramsize, fd) !=
unitprogramsize) {
ret = FAIL;
sprintf(
mess,
"Could not %s. Could not copy program to /var/tmp (size:%ld)\n",
functionType, (long int)unitprogramsize);
LOG(logERROR, (mess));
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
break;
}
// print progress
LOG(logINFO,
("\t%d%%\r",
(int)(((double)(totalsize - filesize) / totalsize) * 100)));
fflush(stdout);
}
free(src);
fclose(fd);
// checksum of copied program
if (ret == OK) {
ret = verifyChecksumFromFile(mess, functionType, checksum,
TEMP_PROG_FILE_NAME);
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
return;
}
// appropriate functions
switch (index) {
case PROGRAM_FPGA:
case PROGRAM_KERNEL:
ret = eraseAndWriteToFlash(mess, index, functionType, checksum,
totalsize);
break;
case PROGRAM_SERVER:
ret = moveBinaryFile(mess, serverName, TEMP_PROG_FILE_NAME,
"update detector server");
if (ret == OK) {
ret = setupDetectorServer(mess, serverName);
}
break;
default:
modeNotImplemented("Program index", (int)index);
break;
}
// erase and copy to flash
Server_SendResult(file_des, INT32, NULL, 0);
#endif
}
void receive_program_default(int file_des, enum PROGRAM_INDEX index,
char *functionType, uint64_t filesize,
char *checksum, char *serverName) {
#if !defined(GOTTHARD2D) && !defined(MYTHEN3D) && !defined(EIGERD)
ret = FAIL;
sprintf(mess,
"Could not %s. program via blackfin not implmented for this "
"detector.\n",
functionType);
LOG(logERROR, (mess))
#else
#if defined(GOTTHARD2D) || defined(MYTHEN3D)
// validate file size
if (filesize > NIOS_MAX_APP_IMAGE_SIZE) {
ret = FAIL;
sprintf(mess,
"Could not %s. File size 0x%llx "
"exceeds max size 0x%llx. Forgot Compression?\n",
functionType, (long long unsigned int)filesize,
(long long unsigned int)NIOS_MAX_APP_IMAGE_SIZE);
LOG(logERROR, (mess));
}
#endif
// memory allocation
char *src = NULL;
if (ret == OK) {
src = malloc(filesize);
if (src == NULL) {
struct sysinfo info;
sysinfo(&info);
sprintf(mess,
"Could not %s. Memory allocation failure. Free "
"space: %d MB\n",
functionType, (int)(info.freeram / (1024 * 1024)));
LOG(logERROR, (mess));
ret = FAIL;
}
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
return;
}
// receive program
if (receiveData(file_des, src, filesize, OTHER) < 0) {
free(src);
ret = printSocketReadError();
return;
}
// checksum of copied program
if (ret == OK) {
ret = verifyChecksumFromBuffer(mess, functionType, checksum, src,
filesize);
}
Server_SendResult(file_des, INT32, NULL, 0);
if (ret == FAIL) {
return;
}
// appropriate functions
switch (index) {
#if defined(GOTTHARD2D) || defined(MYTHEN3D)
case PROGRAM_FPGA:
case PROGRAM_KERNEL:
ret = eraseAndWriteToFlash(mess, index, functionType, checksum, src,
filesize);
break;
#endif
#if defined(GOTTHARD2D) || defined(MYTHEN3D) || defined(EIGERD)
case PROGRAM_SERVER:
ret = writeBinaryFile(mess, TEMP_PROG_FILE_NAME, src, filesize,
"update detector server");
// extra step to write to temp and move to real file as
// fopen will give text busy if opening same name as process name
char dest[MAX_STR_LENGTH] = {0};
sprintf(dest, "%s%s",
(myDetectorType == EIGER ? "/home/root/executables/" : ""),
serverName);
if (ret == OK) {
ret = moveBinaryFile(mess, dest, TEMP_PROG_FILE_NAME,
"update detector server");
}
if (ret == OK) {
ret = verifyChecksumFromFile(mess, functionType, checksum, dest);
}
if (ret == OK) {
ret = setupDetectorServer(mess, dest);
}
break;
#endif
default:
modeNotImplemented("Program index", (int)index);
break;
}
// send result
Server_SendResult(file_des, INT32, NULL, 0);
// free resources
free(src);
#endif
}

View File

@@ -1733,7 +1733,8 @@ class Detector {
/** [Jungfrau][CTB][Moench] Advanced user Function! */
void resetFPGA(Positions pos = {});
/** [Jungfrau][Eiger][Gotthard][CTB][Moench][Mythen3][Gotthard2]
/** [[deprecated ("Replaced by updateDetectorServer, which does not require tftp")]]
* [Jungfrau][Eiger][Gotthard][CTB][Moench][Mythen3][Gotthard2]
* Advanced user Function! \n
* Copy detector server fname from tftp folder of hostname to detector. Also
* creates a symbolic link to a shorter name (without vx.x.x). Then the
@@ -1744,11 +1745,26 @@ class Detector {
void copyDetectorServer(const std::string &fname,
const std::string &hostname, Positions pos = {});
/** [Jungfrau][Eiger][Ctb][Moench][Mythen3][Gotthard2] Copies detector
* server via TCP (without tftp).\nMakes a symbolic link with a shorter
* name (without vx.x.x).\nThen, detector controller reboots (except
* Eiger).\n[Jungfrau][Ctb][Moench]Also changes respawn server to the
* link, which is effective after a reboot.
*/
void updateDetectorServer(const std::string &fname, Positions pos = {});
/** [Jungfrau][Ctb][Moench][Mythen3][Gotthard2] \n
* Advanced Command!! You could damage the detector. Please use with
* caution.\nUpdates the kernel image. Then, detector controller reboots
* with new kernel
*/
void updateKernel(const std::string &fname, Positions pos = {});
/** [Jungfrau][Gotthard][CTB][Moench][Mythen3][Gotthard2] Advanced user
* Function! */
void rebootController(Positions pos = {});
/**
/** [[deprecated ("Replaced by overloaded updateDetectorServer, which does not require tftp and has one less argument")]]
* Advanced user Function!\n [Jungfrau][Gotthard][CTB][Moench] Updates the
* firmware, detector server, make a soft link and then reboots detector
* controller. \n [Mythen3][Gotthard2] Will require a script to start up the
@@ -1760,6 +1776,16 @@ class Detector {
const std::string &hostname,
const std::string &fname, Positions pos = {});
/**
* Advanced user Function!\n [Jungfrau][Gotthard][CTB][Moench] Updates the
* firmware, detector server, make a soft link and then reboots detector
* controller. \n [Mythen3][Gotthard2] Will require a script to start up the
* shorter named server link at start up \n sname is full path name of detector
* server \n fname is programming file name with full path to it
*/
void updateFirmwareAndServer(const std::string &sname,
const std::string &fname, Positions pos = {});
/** Advanced user Function! \n
* Goes to stop server. Hence, can be called while calling blocking
* acquire(). \n [Eiger] Address is +0x100 for only left, +0x200 for only

View File

@@ -285,12 +285,14 @@ std::string CmdProxy::Versions(int action) {
os << "\nFirmware Version: " << OutStringHex(t);
}
os << "\nDetector Server Version: "
<< OutStringHex(det->getDetectorServerVersion(std::vector<int>{det_id}));
<< OutStringHex(
det->getDetectorServerVersion(std::vector<int>{det_id}));
os << "\nDetector Server Version: "
<< OutString(det->getKernelVersion({std::vector<int>{det_id}}));
if (det->getUseReceiverFlag().squash(true)) {
os << "\nReceiver Version: "
<< OutStringHex(det->getReceiverVersion(std::vector<int>{det_id}));
<< OutStringHex(
det->getReceiverVersion(std::vector<int>{det_id}));
}
os << std::dec << '\n';
} else if (action == defs::PUT_ACTION) {
@@ -1432,7 +1434,9 @@ std::string CmdProxy::UDPDestinationList(int action) {
throw sls::RuntimeError("udp_dstlist must be at module level.");
}
if (rx_id < 0 || rx_id >= MAX_UDP_DESTINATION) {
throw sls::RuntimeError(std::string("Invalid receiver index ") + std::to_string(rx_id) + std::string(" to set round robin entry."));
throw sls::RuntimeError(std::string("Invalid receiver index ") +
std::to_string(rx_id) +
std::string(" to set round robin entry."));
}
auto t = det->getDestinationUDPList(rx_id, std::vector<int>{det_id});
os << OutString(t) << '\n';
@@ -2849,11 +2853,13 @@ std::string CmdProxy::CopyDetectorServer(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
LOG(logWARNING) << "Deprecated! Replaced by updatedetectorserver that requires no tftp.\n";
os << "[server_name (in tftp folder)] "
"[pc_host_name]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3]["
"Gotthard2] Copies detector server via tftp from pc. Ensure that "
"Gotthard2] Copies detector server via TFTP from pc. Ensure that "
"server is in the pc's tftp folder. Makes a symbolic link with a "
"shorter name (without vx.x.x). Then, detector reboots (except "
"shorter name (without vx.x.x). Then, detector controller "
"reboots (except "
"Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server "
"to the link, which is effective after a reboot."
<< '\n';
@@ -2871,30 +2877,93 @@ std::string CmdProxy::CopyDetectorServer(int action) {
return os.str();
}
std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) {
std::string CmdProxy::UpdateDetectorServer(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[server_name (in tftp folder)] [pc_host_name] [fname.pof (incl "
"full path)]\n\t[Jungfrau][Gotthard][CTB][Moench] Updates the "
"firmware, detector server, creates the symbolic link and then "
"reboots detector controller. \n\t[Mythen3][Gotthard2] will "
"require a script to start up the shorter named server link at "
"start up. \n\tsname is name of detector server binary found on "
"tftp folder of host pc \n\thostname is name of pc to tftp from "
"\n\tfname is programming file name"
os << "[server_name with full "
"path]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3]["
"Gotthard2] Copies detector server via TCP (without tftp). Makes "
"a symbolic link with a shorter name (without vx.x.x). Then, "
"detector controller reboots (except "
"Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server "
"to the link, which is effective after a reboot."
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get");
} else if (action == defs::PUT_ACTION) {
if (args.size() != 3) {
WrongNumberOfParameters(3);
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
if (args[2].find(".pof") == std::string::npos) {
throw sls::RuntimeError("Programming file must be a pof file.");
det->updateDetectorServer(args[0], std::vector<int>{det_id});
os << "successful\n";
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::UpdateKernel(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[kernel_name with full "
"path]\n\t[Jungfrau][Ctb][Moench][Mythen3]["
"Gotthard2] Advanced Command!! You could damage the detector. "
"Please use"
"with caution.\n\tUpdates the kernel image. Then, detector "
"controller "
"reboots with new kernel."
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get");
} else if (action == defs::PUT_ACTION) {
if (args.size() != 1) {
WrongNumberOfParameters(1);
}
det->updateFirmwareAndServer(args[0], args[1], args[2],
det->updateKernel(args[0], std::vector<int>{det_id});
os << "successful\n";
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "\n\tDeprecated!! Replaced without using tftp (as shown next)[server_name"
" (in tftp folder)] [pc_host_name] [fname.pof (incl full path)]";
os << "\n\t[server_name (incl fullpath)] [fname.pof (incl full path)] "
"This does not use tftp."
"\n\t\t[Jungfrau][Gotthard][CTB][Moench] Updates the "
"firmware, detector server, creates the symbolic link and then "
"reboots detector controller. \n\t[Mythen3][Gotthard2] will "
"require a script to start up the shorter named server link at "
"start up. \n\t\tsname is full path name of detector server binary"
"\n\t\tfname is full path of programming file"
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get");
} else if (action == defs::PUT_ACTION) {
if (args.size() != 3 && args.size() != 2) {
WrongNumberOfParameters(2);
}
int fpos = args.size() - 1;
if (args[fpos].find(".pof") == std::string::npos && args[fpos].find(".rbf") == std::string::npos) {
throw sls::RuntimeError("Programming file must be a pof/rbf file.");
}
if (args.size() == 3) {
LOG(logWARNING) << "Deprecated! Recommend to use same command without tftp (no pc name) and using full path to the server binary";
det->updateFirmwareAndServer(args[0], args[1], args[2],
std::vector<int>{det_id});
} else {
det->updateFirmwareAndServer(args[0], args[1],
std::vector<int>{det_id});
}
os << "successful\n";
} else {
throw sls::RuntimeError("Unknown action");

View File

@@ -1059,6 +1059,8 @@ class CmdProxy {
{"programfpga", &CmdProxy::ProgramFpga},
{"resetfpga", &CmdProxy::resetfpga},
{"copydetectorserver", &CmdProxy::CopyDetectorServer},
{"updatedetectorserver", &CmdProxy::UpdateDetectorServer},
{"updatekernel", &CmdProxy::UpdateKernel},
{"rebootcontroller", &CmdProxy::rebootcontroller},
{"update", &CmdProxy::UpdateFirmwareAndDetectorServer},
{"reg", &CmdProxy::Register},
@@ -1183,6 +1185,8 @@ class CmdProxy {
/* Advanced */
std::string ProgramFpga(int action);
std::string CopyDetectorServer(int action);
std::string UpdateDetectorServer(int action);
std::string UpdateKernel(int action);
std::string UpdateFirmwareAndDetectorServer(int action);
std::string Register(int action);
std::string AdcRegister(int action);

View File

@@ -9,6 +9,7 @@
#include "Module.h"
#include "sls/Pattern.h"
#include "sls/container_utils.h"
#include "sls/file_utils.h"
#include "sls/logger.h"
#include "sls/sls_detector_defs.h"
#include "sls/versionAPI.h"
@@ -2133,6 +2134,7 @@ void Detector::setAdditionalJsonParameter(const std::string &key,
// Advanced
void Detector::programFPGA(const std::string &fname, Positions pos) {
LOG(logINFO) << "Updating Firmware...";
std::vector<char> buffer = pimpl->readProgrammingFile(fname);
pimpl->Parallel(&Module::programFPGA, pos, buffer);
rebootController(pos);
@@ -2144,12 +2146,30 @@ void Detector::resetFPGA(Positions pos) {
void Detector::copyDetectorServer(const std::string &fname,
const std::string &hostname, Positions pos) {
LOG(logINFO) << "Updating Detector Server (via tftp)...";
pimpl->Parallel(&Module::copyDetectorServer, pos, fname, hostname);
if (getDetectorType().squash() != defs::EIGER) {
rebootController(pos);
}
}
void Detector::updateDetectorServer(const std::string &fname, Positions pos) {
LOG(logINFO) << "Updating Detector Server (no tftp)...";
std::vector<char> buffer = readBinaryFile(fname, "Update Detector Server");
std::string filename = sls::getFileNameFromFilePath(fname);
pimpl->Parallel(&Module::updateDetectorServer, pos, buffer, filename);
if (getDetectorType().squash() != defs::EIGER) {
rebootController(pos);
}
}
void Detector::updateKernel(const std::string &fname, Positions pos) {
LOG(logINFO) << "Updating Kernel...";
std::vector<char> buffer = sls::readBinaryFile(fname, "Update Kernel");
pimpl->Parallel(&Module::updateKernel, pos, buffer);
rebootController(pos);
}
void Detector::rebootController(Positions pos) {
pimpl->Parallel(&Module::rebootController, pos);
}
@@ -2158,10 +2178,23 @@ void Detector::updateFirmwareAndServer(const std::string &sname,
const std::string &hostname,
const std::string &fname,
Positions pos) {
LOG(logINFO) << "Updating Firmware and Detector Server (with tftp)...";
LOG(logINFO) << "Updating Detector Server (via tftp)...";
pimpl->Parallel(&Module::copyDetectorServer, pos, sname, hostname);
programFPGA(fname, pos);
}
void Detector::updateFirmwareAndServer(const std::string &sname,
const std::string &fname,
Positions pos) {
LOG(logINFO) << "Updating Firmware and Detector Server (no tftp)...";
LOG(logINFO) << "Updating Detector Server (no tftp)...";
std::vector<char> buffer = readBinaryFile(fname, "Update Detector Server");
std::string filename = sls::getFileNameFromFilePath(sname);
pimpl->Parallel(&Module::updateDetectorServer, pos, buffer, filename);
programFPGA(fname, pos);
}
Result<uint32_t> Detector::readRegister(uint32_t addr, Positions pos) const {
return pimpl->Parallel(&Module::readRegister, pos, addr);
}
@@ -2240,7 +2273,7 @@ Result<sls::IpAddr> Detector::getLastClientIP(Positions pos) const {
Result<std::string> Detector::executeCommand(const std::string &value,
Positions pos) {
return pimpl->Parallel(&Module::execCommand, pos, value);
return pimpl->Parallel(&Module::executeCommand, pos, value);
}
Result<int64_t> Detector::getNumberOfFramesFromStart(Positions pos) const {

View File

@@ -12,6 +12,7 @@
#include "sls/ToString.h"
#include "sls/container_utils.h"
#include "sls/file_utils.h"
#include "sls/network_utils.h"
#include "sls/string_utils.h"
@@ -1261,8 +1262,7 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
throw RuntimeError("programfpga not implemented for this detector");
}
LOG(logINFO)
<< "Updating Firmware. This can take awhile. Please be patient...";
LOG(logINFO) << "This can take awhile. Please be patient.";
LOG(logDEBUG1) << "Programming FPGA with file name:" << fname;
// check if it exists
@@ -1280,14 +1280,7 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
}
// get srcSize to print progress
if (fseek(src, 0, SEEK_END) != 0) {
throw RuntimeError("Program FPGA: Seek error in src file");
}
size_t srcSize = ftell(src);
if (srcSize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of source file");
}
rewind(src);
ssize_t srcSize = sls::getFileSize(src, "Program FPGA");
// create temp destination file
char destfname[] = "/tmp/SLS_DET_MCB.XXXXXX";
@@ -1359,36 +1352,12 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
if (close(dst) != 0) {
throw RuntimeError("Program FPGA: Could not close destination file");
}
LOG(logINFOBLUE) << "File has been converted to " << destfname;
LOG(logINFO) << "File has been converted to " << destfname;
// loading dst file to memory
// FILE *fp = fopen("/tmp/SLS_DET_MCB.tzgmUT", "r");
FILE *fp = fopen(destfname, "r");
if (fp == nullptr) {
throw RuntimeError("Program FPGA: Could not open rawbin file");
}
if (fseek(fp, 0, SEEK_END) != 0) {
throw RuntimeError("Program FPGA: Seek error in rawbin file");
}
size_t filesize = ftell(fp);
if (filesize <= 0) {
throw RuntimeError("Program FPGA: Could not get length of rawbin file");
}
rewind(fp);
std::vector<char> buffer(filesize, 0);
if (fread(buffer.data(), sizeof(char), filesize, fp) != filesize) {
throw RuntimeError("Program FPGA: Could not read rawbin file");
}
if (fclose(fp) != 0) {
throw RuntimeError(
"Program FPGA: Could not close destination file after converting");
}
// unlink(destfname); // delete temporary file
LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory";
LOG(logDEBUG1) << "Read file into memory";
// load converted file to memory
std::vector<char> buffer = readBinaryFile(destfname, "Program FPGA");
// delete temporary
unlink(destfname);
return buffer;
}

View File

@@ -284,7 +284,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
/**
* Convert raw file
* [Jungfrau][Ctb] from pof file
* [Jungfrau][Ctb][Moench] from pof file
* [Mythen3][Gotthard2] from rbf file
* @param fname name of pof/rbf file
* @returns binary of the program

View File

@@ -836,8 +836,9 @@ std::vector<uint64_t> Module::getNumMissingPackets() const {
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
client.Send(F_GET_NUM_MISSING_PACKETS);
if (client.Receive<int>() == FAIL) {
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
throw ReceiverError(
"Receiver " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
} else {
auto nports = client.Receive<int>();
std::vector<uint64_t> retval(nports);
@@ -1172,7 +1173,8 @@ void Module::setReceiverHostname(const std::string &receiverIP) {
LOG(logDEBUG1) << "Setting up Receiver hostname with " << receiverIP;
if (getRunStatus() == RUNNING) {
throw RuntimeError("Cannot set receiver hostname. Acquisition already running. Stop it first.");
throw RuntimeError("Cannot set receiver hostname. Acquisition already "
"running. Stop it first.");
}
if (receiverIP == "none") {
@@ -1529,7 +1531,7 @@ void Module::sendReceiverRateCorrections(const std::vector<int64_t> &t) {
receiver.Send(t);
if (receiver.Receive<int>() == FAIL) {
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
" returned error: " + receiver.readErrorMessage());
" returned error: " + receiver.readErrorMessage());
}
}
@@ -1785,7 +1787,7 @@ void Module::sendVetoPhoton(const int chipIndex,
client.Send(values);
if (client.Receive<int>() == FAIL) {
throw DetectorError("Detector " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
}
@@ -1797,14 +1799,14 @@ void Module::getVetoPhoton(const int chipIndex,
client.Send(chipIndex);
if (client.Receive<int>() == FAIL) {
throw DetectorError("Detector " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
auto nch = client.Receive<int>();
if (nch != shm()->nChan.x) {
throw DetectorError("Could not get veto photon. Expected " +
std::to_string(shm()->nChan.x) + " channels, got " +
std::to_string(nch));
std::to_string(shm()->nChan.x) + " channels, got " +
std::to_string(nch));
}
std::vector<int> gainIndices(nch);
std::vector<int> values(nch);
@@ -2032,7 +2034,7 @@ void Module::getBadChannels(const std::string &fname) const {
client.Send(F_GET_BAD_CHANNELS);
if (client.Receive<int>() == FAIL) {
throw DetectorError("Detector " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
// receive badchannels
auto nch = client.Receive<int>();
@@ -2089,7 +2091,7 @@ void Module::setBadChannels(const std::string &fname) {
}
if (client.Receive<int>() == FAIL) {
throw DetectorError("Detector " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
}
@@ -2403,7 +2405,7 @@ std::map<std::string, std::string> Module::getAdditionalJsonHeader() const {
client.Send(F_GET_ADDITIONAL_JSON_HEADER);
if (client.Receive<int>() == FAIL) {
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
} else {
auto size = client.Receive<int>();
std::string buff(size, '\0');
@@ -2452,7 +2454,7 @@ void Module::setAdditionalJsonHeader(
if (client.Receive<int>() == FAIL) {
throw ReceiverError("Receiver " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
}
@@ -2485,14 +2487,15 @@ void Module::programFPGA(std::vector<char> buffer) {
case JUNGFRAU:
case CHIPTESTBOARD:
case MOENCH:
programFPGAviaBlackfin(buffer);
sendProgram(true, buffer, F_PROGRAM_FPGA, "Update Firmware");
break;
case MYTHEN3:
case GOTTHARD2:
programFPGAviaNios(buffer);
sendProgram(false, buffer, F_PROGRAM_FPGA, "Update Firmware");
break;
default:
throw RuntimeError("Program FPGA is not implemented for this detector");
throw RuntimeError("Updating Firmware via the package is not "
"implemented for this detector");
}
}
@@ -2503,7 +2506,8 @@ void Module::copyDetectorServer(const std::string &fname,
char args[2][MAX_STR_LENGTH]{};
sls::strcpy_safe(args[0], fname.c_str());
sls::strcpy_safe(args[1], hostname.c_str());
LOG(logINFO) << "Sending detector server " << args[0] << " from host "
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): Sending detector server " << args[0] << " from host "
<< args[1];
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_COPY_DET_SERVER);
@@ -2516,12 +2520,51 @@ void Module::copyDetectorServer(const std::string &fname,
throw DetectorError(os.str());
}
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): detector server copied";
<< "): Detector server copied";
}
void Module::updateDetectorServer(std::vector<char> buffer,
const std::string &serverName) {
switch (shm()->detType) {
case JUNGFRAU:
case CHIPTESTBOARD:
case MOENCH:
sendProgram(true, buffer, F_UPDATE_DETECTOR_SERVER,
"Update Detector Server (no tftp)", serverName);
break;
case MYTHEN3:
case GOTTHARD2:
case EIGER:
sendProgram(false, buffer, F_UPDATE_DETECTOR_SERVER,
"Update Detector Server (no tftp)", serverName);
break;
default:
throw RuntimeError("Updating DetectorServer via the package is not implemented "
"for this detector");
}
}
void Module::updateKernel(std::vector<char> buffer) {
switch (shm()->detType) {
case JUNGFRAU:
case CHIPTESTBOARD:
case MOENCH:
sendProgram(true, buffer, F_UPDATE_KERNEL, "Update Kernel");
break;
case MYTHEN3:
case GOTTHARD2:
sendProgram(false, buffer, F_UPDATE_KERNEL, "Update Kernel");
break;
default:
throw RuntimeError("Updating Kernel via the package is not implemented "
"for this detector");
}
}
void Module::rebootController() {
sendToDetector(F_REBOOT_CONTROLLER);
LOG(logINFO) << "Controller rebooted successfully!";
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): Controller rebooted successfully!";
}
uint32_t Module::readRegister(uint32_t addr) const {
@@ -2599,11 +2642,25 @@ sls::IpAddr Module::getLastClientIP() const {
return sendToDetector<sls::IpAddr>(F_GET_LAST_CLIENT_IP);
}
std::string Module::execCommand(const std::string &cmd) {
std::string Module::executeCommand(const std::string &cmd) {
char arg[MAX_STR_LENGTH]{};
char retval[MAX_STR_LENGTH]{};
sls::strcpy_safe(arg, cmd.c_str());
sendToDetector(F_EXEC_COMMAND, arg, retval);
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): Sending command " << cmd;
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_EXEC_COMMAND);
client.Send(arg);
if (client.Receive<int>() == FAIL) {
std::cout << '\n';
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
client.Receive(retval);
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): command executed";
return retval;
}
@@ -3161,7 +3218,7 @@ void Module::setModule(sls_detector_module &module, bool trimbits) {
sendModule(&module, client);
if (client.Receive<int>() == FAIL) {
throw DetectorError("Module " + std::to_string(moduleIndex) +
" returned error: " + client.readErrorMessage());
" returned error: " + client.readErrorMessage());
}
}
@@ -3407,56 +3464,69 @@ sls_detector_module Module::readSettingsFile(const std::string &fname,
return myMod;
}
void Module::programFPGAviaBlackfin(std::vector<char> buffer) {
// send program from memory to detector
LOG(logINFO) << "Sending programming binary (from pof) to module "
<< moduleIndex << " (" << shm()->hostname << ")";
void Module::sendProgram(bool blackfin, std::vector<char> buffer,
const int functionEnum,
const std::string &functionType,
const std::string serverName) {
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): Sending " << functionType;
// send fnum and filesize
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_PROGRAM_FPGA);
client.Send(functionEnum);
uint64_t filesize = buffer.size();
client.Send(filesize);
// checksum
// send checksum
std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize);
LOG(logDEBUG1) << "Checksum:" << checksum;
char cChecksum[MAX_STR_LENGTH];
memset(cChecksum, 0, MAX_STR_LENGTH);
char cChecksum[MAX_STR_LENGTH] = {0};
strcpy(cChecksum, checksum.c_str());
client.Send(cChecksum);
// opening file fail
// send server name
if (functionEnum == F_UPDATE_DETECTOR_SERVER) {
char sname[MAX_STR_LENGTH] = {0};
strcpy(sname, serverName.c_str());
client.Send(sname);
}
// validate memory allocation etc in detector
if (client.Receive<int>() == FAIL) {
std::cout << '\n';
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
// sending program in parts of 2mb each
uint64_t unitprogramsize = 0;
int currentPointer = 0;
while (filesize > 0) {
unitprogramsize = MAX_FPGAPROGRAMSIZE; // 2mb
if (unitprogramsize > filesize) { // less than 2mb
unitprogramsize = filesize;
}
LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize
<< "\t filesize:" << filesize;
// send program
if (blackfin) {
uint64_t unitprogramsize = 0;
int currentPointer = 0;
while (filesize > 0) {
unitprogramsize = MAX_BLACKFIN_PROGRAM_SIZE;
if (unitprogramsize > filesize) {
unitprogramsize = filesize;
}
LOG(logDEBUG) << "unitprogramsize:" << unitprogramsize
<< "\t filesize:" << filesize;
client.Send(&buffer[currentPointer], unitprogramsize);
if (client.Receive<int>() == FAIL) {
std::cout << '\n';
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
client.Send(&buffer[currentPointer], unitprogramsize);
if (client.Receive<int>() == FAIL) {
std::cout << '\n';
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
filesize -= unitprogramsize;
currentPointer += unitprogramsize;
}
filesize -= unitprogramsize;
currentPointer += unitprogramsize;
} else {
client.Send(buffer);
}
// checksum
// tmp checksum verified in detector
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
@@ -3466,134 +3536,56 @@ void Module::programFPGAviaBlackfin(std::vector<char> buffer) {
LOG(logINFO) << "Checksum verified for module " << moduleIndex << " ("
<< shm()->hostname << ")";
// simulating erasing flash
{
LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex
<< " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// erasing takes 65 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 65;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf("%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) *
100));
std::cout << std::flush;
// simulating erasing and writing to
if (blackfin) {
if (functionEnum == F_PROGRAM_FPGA) {
simulatingActivityinDetector("Erasing Flash",
BLACKFIN_ERASE_FLASH_TIME);
simulatingActivityinDetector("Writing to Flash",
BLACKFIN_WRITE_TO_FLASH_TIME);
}
} else {
if (functionEnum == F_PROGRAM_FPGA) {
simulatingActivityinDetector("Erasing Flash",
NIOS_ERASE_FLASH_TIME_FPGA);
simulatingActivityinDetector("Writing to Flash",
NIOS_WRITE_TO_FLASH_TIME_FPGA);
} else if (functionEnum == F_UPDATE_KERNEL) {
simulatingActivityinDetector("Erasing Flash",
NIOS_ERASE_FLASH_TIME_KERNEL);
simulatingActivityinDetector("Writing to Flash",
NIOS_WRITE_TO_FLASH_TIME_KERNEL);
}
printf("\n");
}
// simulating writing to flash
{
LOG(logINFO) << "(Simulating) Writing to Flash for module "
<< moduleIndex << " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// writing takes 30 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 30;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf("%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) *
100));
std::cout << std::flush;
}
printf("\n");
}
// update verified
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
LOG(logINFO) << "FPGA programmed successfully";
LOG(logINFO) << "Module " << moduleIndex << " (" << shm()->hostname
<< "): " << functionType << " udpated successfully";
}
void Module::programFPGAviaNios(std::vector<char> buffer) {
LOG(logINFO) << "Sending programming binary (from rbf) to Module "
void Module::simulatingActivityinDetector(const std::string &functionType,
const int timeRequired) {
LOG(logINFO) << "(Simulating) " << functionType << " for module "
<< moduleIndex << " (" << shm()->hostname << ")";
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.Send(F_PROGRAM_FPGA);
uint64_t filesize = buffer.size();
client.Send(filesize);
// checksum
std::string checksum = sls::md5_calculate_checksum(buffer.data(), filesize);
LOG(logDEBUG1) << "Checksum:" << checksum;
char cChecksum[MAX_STR_LENGTH];
memset(cChecksum, 0, MAX_STR_LENGTH);
strcpy(cChecksum, checksum.c_str());
client.Send(cChecksum);
// validate file size before sending program
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
client.Send(buffer);
// simulating erasing flash
{
LOG(logINFO) << "(Simulating) Erasing Flash for module " << moduleIndex
<< " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
printf("%d%%\r", 0);
std::cout << std::flush;
const int ERASE_TIME = timeRequired;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf(
"%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) * 100));
std::cout << std::flush;
// erasing takes 10 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 10;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf("%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) *
100));
std::cout << std::flush;
}
printf("\n");
}
// simulating writing to flash
{
LOG(logINFO) << "(Simulating) Writing to Flash for module "
<< moduleIndex << " (" << shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
// writing takes 45 seconds, printing here (otherwise need threads
// in server-unnecessary)
const int ERASE_TIME = 45;
int count = ERASE_TIME + 1;
while (count > 0) {
std::this_thread::sleep_for(std::chrono::seconds(1));
--count;
printf("%d%%\r",
static_cast<int>(
(static_cast<double>(ERASE_TIME - count) / ERASE_TIME) *
100));
std::cout << std::flush;
}
printf("\n");
}
if (client.Receive<int>() == FAIL) {
std::ostringstream os;
os << "Module " << moduleIndex << " (" << shm()->hostname << ")"
<< " returned error: " << client.readErrorMessage();
throw DetectorError(os.str());
}
LOG(logINFO) << "FPGA programmed successfully";
printf("\n");
}
} // namespace sls

View File

@@ -541,6 +541,9 @@ class Module : public virtual slsDetectorDefs {
void resetFPGA();
void copyDetectorServer(const std::string &fname,
const std::string &hostname);
void updateDetectorServer(std::vector<char> buffer,
const std::string &serverName);
void updateKernel(std::vector<char> buffer);
void rebootController();
uint32_t readRegister(uint32_t addr) const;
uint32_t writeRegister(uint32_t addr, uint32_t val);
@@ -565,7 +568,7 @@ class Module : public virtual slsDetectorDefs {
bool getLockDetector() const;
void setLockDetector(bool lock);
sls::IpAddr getLastClientIP() const;
std::string execCommand(const std::string &cmd);
std::string executeCommand(const std::string &cmd);
int64_t getNumberOfFramesFromStart() const;
int64_t getActualTime() const;
int64_t getMeasurementTime() const;
@@ -746,11 +749,20 @@ class Module : public virtual slsDetectorDefs {
std::string getTrimbitFilename(detectorSettings settings, int e_eV);
sls_detector_module readSettingsFile(const std::string &fname,
bool trimbits = true);
void programFPGAviaBlackfin(std::vector<char> buffer);
void programFPGAviaNios(std::vector<char> buffer);
void sendProgram(bool blackfin, std::vector<char> buffer,
const int functionEnum, const std::string &functionType,
const std::string serverName = "");
void simulatingActivityinDetector(const std::string &functionType,
const int timeRequired);
const int moduleIndex;
mutable sls::SharedMemory<sharedModule> shm{0, 0};
static const int BLACKFIN_ERASE_FLASH_TIME = 65;
static const int BLACKFIN_WRITE_TO_FLASH_TIME = 30;
static const int NIOS_ERASE_FLASH_TIME_FPGA = 10;
static const int NIOS_WRITE_TO_FLASH_TIME_FPGA = 45;
static const int NIOS_ERASE_FLASH_TIME_KERNEL = 9;
static const int NIOS_WRITE_TO_FLASH_TIME_KERNEL = 40;
};
} // namespace sls

View File

@@ -2708,6 +2708,25 @@ TEST_CASE("copydetectorserver", "[.cmd]") {
}
}
TEST_CASE("updatekernel", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::JUNGFRAU || det_type == defs::CHIPTESTBOARD ||
det_type == defs::MOENCH || det_type == defs::MYTHEN3 ||
det_type == defs::GOTTHARD2) {
// TODO: send real server?
// std::ostringstream oss;
// proxy.Call("updatekernel",{"juImage_detector.lzma",
// "pc13784"}, -1, PUT, oss);
// REQUIRE(oss.str() == "updatekernel successful\n");
REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET));
} else {
REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("updatekernel", {}, -1, PUT));
}
}
TEST_CASE("rebootcontroller", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);

View File

@@ -355,7 +355,7 @@ std::string Implementation::getFilePath() const { return filePath; }
void Implementation::setFilePath(const std::string &c) {
if (!c.empty()) {
mkdir_p(c); // throws if it can't create
sls::mkdir_p(c); // throws if it can't create
filePath = c;
}
LOG(logINFO) << "File path: " << filePath;

View File

@@ -8,49 +8,46 @@
#include <fstream>
#include <string>
/** (used by multi and sls)
* reads a short int raw data file
* @param infile input file stream
namespace sls {
/**
* @param data array of data values
* @param nch number of channels
* @param offset start channel value
* @returns OK or FAIL if it could not read the file or data=NULL
*/
int readDataFile(std::ifstream &infile, short int *data, int nch,
int offset = 0);
/** (used by multi and sls)
* reads a short int rawdata file
* @param fname name of the file to be read
/**
* @param data array of data value
* @param nch number of channels
* @returns OK or FAIL if it could not read the file or data=NULL
*/
int readDataFile(std::string fname, short int *data, int nch);
/** (used by multi and sls)
* writes a short int raw data file
* @param outfile output file stream
std::vector<char> readBinaryFile(const std::string &fname,
const std::string &errorPrefix);
/**
* @param nch number of channels
* @param data array of data values
* @param offset start channel number
* @returns OK or FAIL if it could not write the file or data=NULL
*/
int writeDataFile(std::ofstream &outfile, int nch, short int *data,
int offset = 0);
/** (used by multi and sls)
* writes a short int raw data file
* @param fname of the file to be written
/**
* @param nch number of channels
* @param data array of data values
* @returns OK or FAIL if it could not write the file or data=NULL
*/
int writeDataFile(std::string fname, int nch, short int *data);
// mkdir -p path implemented by recursive calls
void mkdir_p(const std::string &path, std::string dir = "");
namespace sls {
int getFileSize(std::ifstream &ifs);
ssize_t getFileSize(FILE* fd, const std::string &prependErrorString);
std::string getFileNameFromFilePath(const std::string &fpath);
}

View File

@@ -55,9 +55,8 @@
/** maximum trim en */
#define MAX_TRIMEN 100
/** maximum unit size of program sent to detector */
//#define MAX_FPGAPROGRAMSIZE (2 * 1024 * 1024)
#define MAX_FPGAPROGRAMSIZE (128 * 1024)
/** maximum unit size of program sent to blackfin */
#define MAX_BLACKFIN_PROGRAM_SIZE (128 * 1024)
#define GET_FLAG -1

View File

@@ -254,6 +254,8 @@ enum detFuncs {
F_GET_READOUT_SPEED,
F_SET_READOUT_SPEED,
F_GET_KERNEL_VERSION,
F_UPDATE_KERNEL,
F_UPDATE_DETECTOR_SERVER,
NUM_DET_FUNCTIONS,
RECEIVER_ENUM_START = 256, /**< detector function should not exceed this
@@ -610,6 +612,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_GET_READOUT_SPEED: return "F_GET_READOUT_SPEED";
case F_SET_READOUT_SPEED: return "F_SET_READOUT_SPEED";
case F_GET_KERNEL_VERSION: return "F_GET_KERNEL_VERSION";
case F_UPDATE_DETECTOR_SERVER: return "F_UPDATE_DETECTOR_SERVER";
case NUM_DET_FUNCTIONS: return "NUM_DET_FUNCTIONS";
case RECEIVER_ENUM_START: return "RECEIVER_ENUM_START";

View File

@@ -6,10 +6,10 @@
#define APILIB 0x211027
#define APIRECEIVER 0x211020
#define APIGUI 0x211021
#define APICTB 0x211103
#define APIGOTTHARD 0x211103
#define APIGOTTHARD2 0x211103
#define APIJUNGFRAU 0x211103
#define APIMYTHEN3 0x211103
#define APIMOENCH 0x211103
#define APIEIGER 0x211103
#define APICTB 0x211117
#define APIGOTTHARD 0x211117
#define APIGOTTHARD2 0x211117
#define APIJUNGFRAU 0x211117
#define APIMYTHEN3 0x211117
#define APIMOENCH 0x211111
#define APIEIGER 0x211117

View File

@@ -11,6 +11,8 @@
#include <sys/stat.h>
#include <sys/types.h>
namespace sls {
int readDataFile(std::ifstream &infile, short int *data, int nch, int offset) {
int ichan, iline = 0;
short int idata;
@@ -53,6 +55,39 @@ int readDataFile(std::string fname, short int *data, int nch) {
return iline;
}
std::vector<char> readBinaryFile(const std::string &fname,
const std::string &errorPrefix) {
// check if it exists
struct stat st;
if (stat(fname.c_str(), &st) != 0) {
throw sls::RuntimeError(errorPrefix +
std::string(" (file does not exist)"));
}
FILE *fp = fopen(fname.c_str(), "rb");
if (fp == nullptr) {
throw sls::RuntimeError(errorPrefix +
std::string(" (Could not open file: ") + fname + std::string(")"));
}
// get file size to print progress
ssize_t filesize = sls::getFileSize(fp, errorPrefix);
std::vector<char> buffer(filesize, 0);
if ((ssize_t)fread(buffer.data(), sizeof(char), filesize, fp) != filesize) {
throw sls::RuntimeError(errorPrefix +
std::string(" (Could not read file)"));
}
if (fclose(fp) != 0) {
throw sls::RuntimeError(errorPrefix +
std::string(" (Could not close file)"));
}
LOG(logDEBUG1) << "Read file into memory";
return buffer;
}
int writeDataFile(std::ofstream &outfile, int nch, short int *data,
int offset) {
if (data == nullptr)
@@ -96,7 +131,6 @@ void mkdir_p(const std::string &path, std::string dir) {
mkdir_p(path.substr(i + 1), dir);
}
namespace sls {
int getFileSize(std::ifstream &ifs) {
auto current_pos = ifs.tellg();
ifs.seekg(0, std::ios::end);
@@ -104,4 +138,27 @@ int getFileSize(std::ifstream &ifs) {
ifs.seekg(current_pos);
return file_size;
}
std::string getFileNameFromFilePath(const std::string &fpath) {
std::string fname(fpath);
std::size_t slashPos = fpath.rfind('/');
if (slashPos != std::string::npos) {
fname = fpath.substr(slashPos + 1, fpath.size() - 1);
}
return fname;
}
ssize_t getFileSize(FILE* fd, const std::string &prependErrorString) {
if (fseek(fd, 0, SEEK_END) != 0) {
throw RuntimeError(prependErrorString + std::string(" (Seek error in src file)"));
}
size_t fileSize = ftell(fd);
if (fileSize <= 0) {
throw RuntimeError(prependErrorString + std::string(" (Could not get length of source file)"));
}
rewind(fd);
return fileSize;
}
} // namespace sls