DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
daphnemodules
src
DaphneV2Interface.cpp
Go to the documentation of this file.
1
8
9
#include "
DaphneV2Interface.hpp
"
10
#include "
logging/Logging.hpp
"
11
#include <sys/time.h>
12
13
using namespace
dunedaq::daphnemodules
;
14
15
DaphneV2Interface::DaphneV2Interface
(
const
char
* ipaddr,
int
port, std::chrono::milliseconds timeout)
16
:
m_timeout
(timeout)
17
{
18
19
m_connection_id
= socket(AF_INET, SOCK_DGRAM, 0);
20
21
if
(
m_connection_id
< 0)
22
throw
SocketCreationError(
ERS_HERE
);
23
24
m_target
.sin_family = AF_INET;
25
m_target
.sin_port = htons(port);
26
auto
ret = inet_pton(AF_INET, ipaddr, &(
m_target
.sin_addr));
27
if
(ret <= 0)
28
throw
InvalidIPAddress
(
ERS_HERE
, ipaddr);
29
30
m_ip
= ipaddr;
31
32
if
(!
validate_connection
())
33
throw
FailedPing(
ERS_HERE
, ipaddr, port);
34
}
35
36
void
37
DaphneV2Interface::close
()
38
{
39
40
::close
(
m_connection_id
);
41
}
42
43
bool
44
DaphneV2Interface::validate_connection
()
const
45
{
46
47
auto
ret =
read_register
(0xaa55, 1);
48
49
static
const
uint64_t good_value = 0xdeadbeef;
50
return
ret[0] == good_value;
51
}
52
53
command_result
54
DaphneV2Interface::send_command_retry
(std::string cmd,
size_t
retry)
const
55
{
56
57
do
{
58
try
{
59
auto
ret =
send_command
(cmd);
60
return
ret;
61
}
catch
(
const
CommandTimeout& e) {
62
ers::warning
(e);
63
--retry;
64
}
catch
(
const
ers::Issue
& e) {
65
throw
FailedSocketInteraction
(
ERS_HERE
, cmd, e);
66
}
67
68
}
while
(retry > 0);
69
70
throw
FailedSocketInteraction
(
ERS_HERE
, cmd);
71
}
72
73
command_result
74
DaphneV2Interface::send_command_interruptible
(std::string cmd, std::function<
bool
()> can_retry)
const
75
{
76
77
do
{
78
try
{
79
auto
ret =
send_command
(cmd);
80
return
ret;
81
}
catch
(
const
CommandTimeout& e) {
82
ers::warning
(e);
83
}
catch
(
const
ers::Issue
& e) {
84
throw
FailedSocketInteraction
(
ERS_HERE
, cmd, e);
85
}
86
87
}
while
(can_retry());
88
}
89
90
command_result
91
DaphneV2Interface::send_command
(std::string cmd)
const
92
{
93
94
TLOG
() <<
"Board: "
<<
m_ip
<<
", sending command "
<< cmd;
95
std::vector<uint64_t> bytes;
96
for
(
char
ch : cmd) {
97
bytes.push_back(
static_cast<
uint64_t
>
(ch));
98
}
99
bytes.push_back(0x0d);
// dedicated command flag
100
101
const
std::lock_guard<std::mutex> lock(
m_command_mutex
);
102
103
// we send the bytes in chunks of 50 words
104
for
(
size_t
i = 0; i < (bytes.size() + 49) / 50; ++i) {
105
std::vector<uint64_t> part(bytes.begin() + i * 50, bytes.begin() + std::min((i + 1) * 50, bytes.size()));
106
write_buffer
(0x90000000, std::move(part));
107
}
108
109
TLOG
() <<
"Board: "
<<
m_ip
<<
", Command sent, waiting for result"
;
110
111
command_result
res;
112
std::string* writing_pointer =
nullptr
;
113
114
auto
start_time
= std::chrono::high_resolution_clock::now();
115
116
int
more = 40;
117
while
(more > 0) {
118
auto
data_block =
read_buffer
(0x90000000, 50);
119
for
(
size_t
i = 0; i < data_block.size(); ++i) {
120
if
(data_block[i] == 255) {
121
break
;
122
}
else
if
(data_block[i] == 1) {
123
// the following data are returning the command that was issued
124
writing_pointer = &res.
command
;
125
}
else
if
(data_block[i] == 2) {
126
// the following data are the immediate command response
127
writing_pointer = &res.
result
;
128
}
else
if
(data_block[i] == 3) {
129
// this is the message end
130
writing_pointer =
nullptr
;
131
}
else
if
(isprint(
static_cast<
int
>
(data_block[i]))) {
132
more = 40;
133
char
c =
static_cast<
char
>
(data_block[i]);
134
if
(writing_pointer) {
135
*writing_pointer +=
static_cast<
char
>
(data_block[i]);
136
}
else
{
137
TLOG
() <<
"Failed adding charachter "
<< c;
138
}
139
}
140
}
141
auto
now = std::chrono::high_resolution_clock::now();
142
143
auto
delay = now -
start_time
;
144
145
if
(delay >
m_timeout
) {
146
TLOG
() <<
"Details of timeout"
;
147
for
(
size_t
i = 0; i < data_block.size(); ++i) {
148
TLOG
() << i <<
"\t"
<< std::hex << data_block[i] << std::dec;
149
}
150
TLOG
() <<
"Received so far: "
<< res.
result
;
151
auto
delay_us = std::chrono::duration_cast<std::chrono::microseconds>(delay);
152
throw
CommandTimeout(
ERS_HERE
, cmd, delay_us.count());
153
}
154
155
std::this_thread::sleep_for(std::chrono::milliseconds(1));
156
--more;
157
}
158
159
return
res;
160
}
161
162
std::vector<uint64_t>
163
DaphneV2Interface::read
(uint8_t command_id, uint64_t addr, uint8_t
size
)
const
164
{
165
166
const
std::lock_guard<std::mutex> lock(
m_access_mutex
);
167
168
uint8_t cmd[10];
169
cmd[0] = command_id;
170
cmd[1] =
size
;
171
memcpy(cmd + 2, &addr,
sizeof
(uint64_t));
172
auto
result = sendto(
m_connection_id
, cmd,
sizeof
(cmd), 0, (
struct
sockaddr*)&
m_target
,
sizeof
(
m_target
));
173
174
if
(result < 0)
175
throw
FailedSocketInteraction
(
ERS_HERE
,
"sendto"
);
176
177
struct
timeval timeout;
178
timeout.tv_sec =
m_timeout
.count() / 1000;
179
timeout.tv_usec = (
m_timeout
.count() % 1000) * 1000;
180
fd_set readfds, masterfds;
181
182
FD_ZERO(&masterfds);
183
FD_SET(
m_connection_id
, &masterfds);
184
185
memcpy(&readfds, &masterfds,
sizeof
(fd_set));
186
187
auto
start_time
= std::chrono::high_resolution_clock::now();
188
189
if
(select(
m_connection_id
+ 1, &readfds, NULL, NULL, &timeout) < 0) {
190
throw
FailedSocketInteraction
(
ERS_HERE
,
"select"
);
191
}
192
193
std::vector<uint64_t> ret_value;
194
195
if
(FD_ISSET(
m_connection_id
, &readfds)) {
196
uint8_t buffer[2 + (8 *
size
)];
197
socklen_t addrlen =
sizeof
(
m_target
);
198
result = recvfrom(
m_connection_id
, buffer,
sizeof
(buffer), 0, (
struct
sockaddr*)&
m_target
, &addrlen);
199
200
if
(result <= 0)
201
throw
FailedSocketInteraction
(
ERS_HERE
,
"recvfrom"
);
202
203
uint8_t fmt[4 +
size
];
204
fmt[0] =
'<'
;
205
fmt[1] =
'B'
;
206
fmt[2] =
'B'
;
207
fmt[3] =
size
;
208
for
(
int
i = 0; i <
size
; i++) {
209
fmt[4 + i] =
'Q'
;
210
}
211
212
for
(
int
i = 0; i <
size
; i++) {
213
uint64_t value;
214
memcpy(&value, buffer + 2 + (8 * i),
sizeof
(uint64_t));
215
ret_value.push_back(value);
216
}
217
218
}
else
{
219
// the socket timedout
220
auto
end_time = std::chrono::high_resolution_clock::now();
221
auto
duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time -
start_time
);
222
223
throw
SocketTimeout(
ERS_HERE
, duration.count());
224
}
225
226
return
ret_value;
227
}
228
229
void
230
DaphneV2Interface::write
(uint8_t command_id, uint64_t addr, std::vector<uint64_t>&& data)
const
231
{
232
233
const
std::lock_guard<std::mutex> lock(
m_access_mutex
);
234
235
uint8_t cmd[10 + (8 * data.size())];
236
cmd[0] = command_id;
237
cmd[1] = data.size();
238
memcpy(cmd + 2, &addr,
sizeof
(uint64_t));
239
for
(
size_t
i = 0; i < data.size(); i++) {
240
memcpy(cmd + 10 + (8 * i), &(data[i]),
sizeof
(uint64_t));
241
}
242
243
auto
result = sendto(
m_connection_id
, cmd,
sizeof
(cmd), 0, (
struct
sockaddr*)&
m_target
,
sizeof
(
m_target
));
244
if
(result < 0)
245
throw
FailedSocketInteraction
(
ERS_HERE
,
"sendto"
);
246
}
DaphneV2Interface.hpp
ERS_HERE
#define ERS_HERE
Definition
LocalContext.hpp:127
dunedaq::daphnemodules::DaphneV2Interface::m_access_mutex
std::mutex m_access_mutex
Definition
DaphneV2Interface.hpp:105
dunedaq::daphnemodules::DaphneV2Interface::validate_connection
bool validate_connection() const
Definition
DaphneV2Interface.cpp:44
dunedaq::daphnemodules::DaphneV2Interface::write
void write(uint8_t command_id, uint64_t addr, std::vector< uint64_t > &&data) const
Definition
DaphneV2Interface.cpp:230
dunedaq::daphnemodules::DaphneV2Interface::m_ip
std::string m_ip
Definition
DaphneV2Interface.hpp:101
dunedaq::daphnemodules::DaphneV2Interface::close
void close()
Definition
DaphneV2Interface.cpp:37
dunedaq::daphnemodules::DaphneV2Interface::read_buffer
std::vector< uint64_t > read_buffer(uint64_t addr, uint8_t size) const
Definition
DaphneV2Interface.hpp:81
dunedaq::daphnemodules::DaphneV2Interface::m_connection_id
int m_connection_id
Definition
DaphneV2Interface.hpp:102
dunedaq::daphnemodules::DaphneV2Interface::read
std::vector< uint64_t > read(uint8_t command_id, uint64_t addr, uint8_t size) const
Definition
DaphneV2Interface.cpp:163
dunedaq::daphnemodules::DaphneV2Interface::write_buffer
void write_buffer(uint64_t addr, std::vector< uint64_t > &&data) const
Definition
DaphneV2Interface.hpp:82
dunedaq::daphnemodules::DaphneV2Interface::send_command_retry
command_result send_command_retry(std::string cmd, size_t retry=std::numeric_limits< size_t >::max()) const
Definition
DaphneV2Interface.cpp:54
dunedaq::daphnemodules::DaphneV2Interface::m_command_mutex
std::mutex m_command_mutex
Definition
DaphneV2Interface.hpp:106
dunedaq::daphnemodules::DaphneV2Interface::DaphneV2Interface
DaphneV2Interface(const char *ipaddr, int port, std::chrono::milliseconds timeout=std::chrono::milliseconds(500))
Definition
DaphneV2Interface.cpp:15
dunedaq::daphnemodules::DaphneV2Interface::read_register
std::vector< uint64_t > read_register(uint64_t addr, uint8_t size) const
Definition
DaphneV2Interface.hpp:78
dunedaq::daphnemodules::DaphneV2Interface::send_command
command_result send_command(std::string cmd) const
Definition
DaphneV2Interface.cpp:91
dunedaq::daphnemodules::DaphneV2Interface::send_command_interruptible
command_result send_command_interruptible(std::string cmd, std::function< bool()> can_retry) const
Definition
DaphneV2Interface.cpp:74
dunedaq::daphnemodules::DaphneV2Interface::m_timeout
std::chrono::milliseconds m_timeout
Definition
DaphneV2Interface.hpp:104
dunedaq::daphnemodules::DaphneV2Interface::m_target
sockaddr_in m_target
Definition
DaphneV2Interface.hpp:103
ers::Issue
Base class for any user define issue.
Definition
Issue.hpp:76
Logging.hpp
TLOG
#define TLOG(...)
Definition
macro.hpp:21
dunedaq::daphnemodules
Definition
DaphneV2Interface.hpp:53
dunedaq::FailedSocketInteraction
FailedSocketInteraction
Definition
DaphneV2Interface.hpp:39
dunedaq::size
FELIX Initialization std::string initerror FELIX queue timed std::string queuename Unexpected chunk size
Definition
FelixIssues.hpp:30
dunedaq::start_time
Cannot add TPSet with start_time
Definition
TPBundleHandler.hpp:41
dunedaq::InvalidIPAddress
InvalidIPAddress
Definition
CommonIssues.hpp:26
ers::warning
void warning(const Issue &issue)
Definition
ers.hpp:150
dunedaq::daphnemodules::command_result
Definition
DaphneV2Interface.hpp:56
dunedaq::daphnemodules::command_result::result
std::string result
Definition
DaphneV2Interface.hpp:58
dunedaq::daphnemodules::command_result::command
std::string command
Definition
DaphneV2Interface.hpp:57
Generated on
for DUNE-DAQ by
1.18.0