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