GCC Code Coverage Report


Directory: ./
File: src/Master.cpp
Date: 2026-10-12 15:11:37
Exec Total Coverage
Lines: 1 58 1.7%
Branches: 0 82 0.0%

Line Branch Exec Source
1 /*****************************************************************************
2 *
3 * This file is part of the ecapp library (EtherCAT application devices).
4 *
5 * Copyright (C) 2026 Florian Pose <fp@igh.de>
6 *
7 * The ecapp library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation, version 3 of the
10 * License.
11 *
12 * The ecapp library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with the ecapp library. If not, see
19 * <https://www.gnu.org/licenses/>.
20 *
21 ****************************************************************************/
22
23 #include "ecapp/Master.h"
24
25 #include <cstdio>
26 #include <cstring>
27 #include <iostream>
28 #include <sstream>
29 #include <stdexcept>
30 #include <string>
31
32 using std::cerr;
33 using std::endl;
34 using std::invalid_argument;
35 using std::runtime_error;
36 using std::string;
37 using std::stringstream;
38
39 /****************************************************************************/
40
41 namespace EcApp {
42
43 struct Master::Impl
44 {
45 ec_master_t *master;
46 unsigned int sync_cycles;
47 unsigned int sync_ref_counter;
48 unsigned int slaves_responding;
49 uint8_t al_states;
50 bool link_up;
51 uint32_t dc_deviation;
52 };
53
54 /****************************************************************************/
55
56 ✗ Master::Master(pdserv *pdserv, pdtask *task) :
57 impl(new Impl {
58 NULL,
59 1,
60 0,
61 0U,
62 0x00,
63 false,
64 0U,
65 ✗ })
66 {
67 ✗ string prefix("/EtherCAT");
68
69 ✗ if (!(impl->master = ecrt_request_master(0))) {
70 ✗ stringstream err;
71 ✗ err << "Requesting master 0 failed!";
72 ✗ cerr << err.str() << endl;
73 ✗ throw invalid_argument("config failed");
74 }
75
76 ✗ if (pdserv && task) {
77 ✗ pdserv_parameter(
78 ✗ pdserv, (prefix + "/SyncCycles").c_str(), 0666, pd_uint32_T,
79 ✗ &impl->sync_cycles, 1, NULL, NULL, NULL);
80 ✗ pdserv_signal(
81 ✗ task, 1, (prefix + "/SyncRefCounter").c_str(), pd_uint32_T,
82 ✗ &impl->sync_ref_counter, 1, NULL);
83 ✗ pdserv_signal(
84 ✗ task, 1, (prefix + "/SlavesResponding").c_str(), pd_uint32_T,
85 ✗ &impl->slaves_responding, 1, NULL);
86 ✗ pdserv_signal(
87 ✗ task, 1, (prefix + "/ApplicationLayerStates").c_str(),
88 ✗ pd_uint32_T, &impl->al_states, 1, NULL);
89 ✗ pdserv_signal(
90 ✗ task, 1, (prefix + "/LinkUp").c_str(), pd_boolean_T,
91 ✗ &impl->link_up, 1, NULL);
92 ✗ pdserv_signal(
93 ✗ task, 1, (prefix + "/DcDeviation").c_str(), pd_uint32_T,
94 ✗ &impl->dc_deviation, 1, NULL);
95 }
96 }
97
98 /****************************************************************************/
99
100 ✗ Master::~Master()
101 {
102 ✗ ecrt_release_master(impl->master);
103 }
104
105 /****************************************************************************/
106
107 ✗ ec_master_t *Master::getMaster()
108 {
109 ✗ return impl->master;
110 }
111
112 /****************************************************************************/
113
114 ✗ void Master::activate()
115 {
116 {
117 ✗ stringstream msg;
118 ✗ msg << "Activating master...";
119 ✗ cerr << msg.str() << endl;
120 }
121
122 ✗ if (ecrt_master_activate(impl->master)) {
123 ✗ throw runtime_error("Failed to activate master!");
124 }
125 }
126
127 /****************************************************************************/
128
129 ✗ void Master::receive()
130 {
131 // receive datagrams
132 ✗ ecrt_master_receive(impl->master);
133
134 ec_master_state_t state;
135 ✗ ecrt_master_state(impl->master, &state);
136 ✗ impl->slaves_responding = state.slaves_responding;
137 ✗ impl->al_states = state.al_states;
138 ✗ impl->link_up = state.link_up;
139
140 ✗ impl->dc_deviation = ecrt_master_sync_monitor_process(impl->master);
141 }
142
143 /****************************************************************************/
144
145 ✗ void Master::send()
146 {
147 struct timespec t;
148 ✗ clock_gettime(CLOCK_MONOTONIC, &t);
149 ✗ ecrt_master_application_time(
150 ✗ impl->master, t.tv_sec * 1000000000ULL + t.tv_nsec);
151
152 ✗ if (!impl->sync_ref_counter) {
153 ✗ ecrt_master_sync_reference_clock(impl->master);
154 }
155 ✗ ecrt_master_sync_slave_clocks(impl->master);
156 ✗ ecrt_master_sync_monitor_queue(impl->master);
157
158 ✗ ecrt_master_send(impl->master);
159
160 ✗ if (impl->sync_ref_counter) {
161 ✗ impl->sync_ref_counter--;
162 }
163 else {
164 ✗ impl->sync_ref_counter =
165 ✗ impl->sync_cycles > 0 ? impl->sync_cycles - 1 : 0;
166 }
167 }
168
169 36 } // namespace EcApp
170
171 /****************************************************************************/
172