BusIO.h
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * Copyright (C) 2011-2017, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5 *
6 * ArmarX is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * ArmarX is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * @package ArmarX
19 * @author Stefan Reither( stefan dot reither at kit dot edu)
20 * @date 2021
21 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22 * GNU General Public License
23 */
24
25
26#pragma once
27
28#include <array>
29#include <atomic>
30#include <cstdint>
31#include <mutex>
32#include <thread>
33
34#include "ESI.h"
35#include "RequestQueue.h"
36#include "SlaveRegisters.h"
37#include "Timeouts.h"
38
40{
43 class SDOUpdateRequest;
46
47 struct EtherCATFrame;
48 struct EtherCATFrameList;
49
50 /**
51 * @class BusIO
52 * @ingroup Library-ethercat
53 * @brief Brief description of class BusIO.
54 *
55 * Detailed description of class BusIO.
56 */
57 class BusIO : public ESIHandler
58 {
59 public:
60 virtual ~BusIO();
61
62 /**
63 * Performs a SDO write to a single entry to the slave with the give slaveIndex
64 * and returns true if it succeeds.
65 * Fails if the bus has not been started yet.
66 *
67 * Blocking until the write has been performed or a timeout is reached.
68 *
69 * @param [IN] slaveIndex the slavenumber of the slave on the bus
70 * @param [IN] index the index of the entry where the value is written to
71 * @param [IN] subIndex the subindex of the entry
72 * @param [IN] value the value that will be written to the slave
73 * @param [IN] completeAccess with this flag you can activate writing in complete access
74 * mode
75 * @return true when write was successful otherwise false
76 */
77 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
78 bool
79 writeSDOEntry(std::uint16_t slaveIndex,
80 std::uint16_t index,
81 std::uint8_t subIndex,
82 T value,
83 bool completeAccess = false)
84 {
85 return generalSDOWrite(
86 slaveIndex, index, subIndex, sizeof(value), &value, completeAccess);
87 }
88
89 /**
90 * Performs a SDO write to the slave with the given slaveIndex and returns true if it
91 * succeeds.
92 * Fails if the bus has not been started yet.
93 *
94 * Blocking until the write has been performed or a timeout is reached.
95 *
96 * @param [IN] slaveIndex the slavenumber of the slave on the bus
97 * @param [IN] index the index of the entry where the value is written to
98 * @param [IN] subIndex the subindex of the entry
99 * @param [IN] buflen length of the buffer containing the data
100 * @param [IN] buf buffer containing the data to write
101 * @param [IN] completeAccess with this flag you can activate writing in complete access
102 * mode
103 * @return true when write was successful otherwise false
104 */
105 bool
106 writeSDOByteBuffer(std::uint16_t slaveIndex,
107 std::uint16_t index,
108 std::uint8_t subIndex,
109 int buflen,
110 const unsigned char* buf,
111 bool completeAccess = false)
112 {
113 return generalSDOWrite(slaveIndex, index, subIndex, buflen, buf, completeAccess);
114 }
115
116 /**
117 * Performs a SDO read of an single entry from the slave and returns true if it
118 * succeeds.
119 * Fails if the bus has not been started yet.
120 *
121 * Blocking until the write has been performed or a timeout is reached.
122 *
123 * @param [IN] slaveIndex the index of the slave it will read from
124 * @param [IN] index the index of the object dictonary it will read from
125 * @param [IN] subIndex the sub index of the entry
126 * @param [OUT] result the read data
127 * @param [IN] completeAccess with this flag you can activate writing in complete access
128 * mode
129 * @return true when write was successful otherwise false
130 */
131 template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
132 bool
133 readSDOEntry(std::uint16_t slaveIndex,
134 std::uint16_t index,
135 std::uint8_t subIndex,
136 T& result,
137 bool completeAccess = false)
138 {
139 int buflen = sizeof(result);
140 return generalSDORead(slaveIndex, index, subIndex, &buflen, &result, completeAccess);
141 }
142
143 /**
144 * Performs a SDO read from the slave and returns true if it
145 * succeeds.
146 * Fails if the bus has not been started yet.
147 *
148 * Blocking until the write has been performed or a timeout is reached.
149 *
150 * @param [IN] slaveIndex the index of the slave it will read from
151 * @param [IN] index the index of the object dictonary it will read from
152 * @param [IN] subIndex the sub index of the entry
153 * @param [IN] buflen amount of bytes to read
154 * @param [OUT] buf buffer which contains the read data afterwards
155 * @param [IN] completeAccess with this flag you can activate writing in complete access
156 * mode
157 * @return true when write was successful otherwise false
158 */
159 bool
160 readSDOByteBuffer(std::uint16_t slaveIndex,
161 std::uint16_t index,
162 std::uint8_t subIndex,
163 int* buflen,
164 unsigned char* buf,
165 bool completeAccess = false)
166 {
167 return generalSDORead(slaveIndex, index, subIndex, buflen, buf, completeAccess);
168 }
169
171 changeStateOfSlave(std::uint16_t slaveIndex, EtherCATState state, bool validate = true);
172 EtherCATState changeStateOfBus(EtherCATState state, bool validate = true);
173
175
176 bool resetErrorRegisters(std::uint16_t slaveIndex);
177
178 bool readRegisters(std::vector<RegisterDataList>& registerData);
179 bool readRegisters(EtherCATFrameList* frames, std::uint16_t amountFramesToRead = 0);
180
181 /**
182 * This deactivates the Complete access mode in CoE for the given slave.
183 * For Elmo's it is necessary to deactivate the CA mode otherwise SOEM isn't able to bring
184 * them into OP-Mode
185 * @param slave the slave for which the CA mode will be deactivated
186 */
187 void deactivateCOECA(std::uint16_t slaveIndex);
188
189 void setTimeouts(Timeouts const& timeouts);
190
191 protected:
192 BusIO();
193
194 /**
195 * @brief Updates the PDO of all slaves.
196 * This function has priority over all other BusIO functions and can only be executed by the
197 * Bus itself.
198 */
199 void rtUpdatePDO();
200
201 bool sdoAccessAvailable = false;
202 bool pdoAccessAvailable = false;
203
205
207
208 /** @brief IOmap the IO map where the process data are mapped in */
209 using IOMap = std::array<char, 4096>;
210 alignas(alignof(std::max_align_t)) IOMap ioMap;
211
212
213 private:
214 bool generalSDOWrite(std::uint16_t slaveIndex,
215 std::uint16_t index,
216 std::uint8_t subIndex,
217 std::uint16_t buflen,
218 const void* buf,
219 bool completeAccess = false);
220
221 bool generalSDORead(std::uint16_t slaveIndex,
222 std::uint16_t index,
223 std::uint8_t subIndex,
224 int* buflen,
225 void* buf,
226 bool completeAccess = false);
227
228 bool isSDOAccessAvailable() const;
229
230 /*!
231 * \brief Sends an EtherCAT frame over the EtherCAT bus, receives it and returns the
232 * index of the SOEM buffer the resulting frame was placed in along with the working
233 * counter returned by SOEM.
234 *
235 * This method will automatically place the given slave address at the given offsets
236 * in the final EtherCAT frame in the buffer. Pass an empty offset vector if you do not
237 * require this.
238 * \param frame the EtherCAT frame to send over the bus
239 * \param frameLength the length of the EtherCAT frame in bytes
240 * \param slaveConfiguredAddress the configured address of the slave to send the frame to,
241 * if it needs to be set in the frame
242 * \param slaveAddressOffsets the offsets in the EtherCAT frame to write the configured
243 * address of the slave to
244 * \return the working counter of the frame as returned by SOEM and the index of the SOEM
245 * rx frame buffer the received frame has been placed in.
246 */
247 std::pair<int, int>
248 sendAndReceiveEtherCATFrame(const EtherCATFrame* frame,
249 size_t frameLength,
250 uint16_t slaveConfiguredAddress,
251 const std::vector<size_t>& slaveAddressOffsets);
252
253 RequestQueue requestQueues;
254
255 std::thread requestHandlerThread;
256 std::atomic_bool requestHandlerThreadRunning{true};
257 std::atomic_bool pdoUpdateRequested{false};
258
259 void requestHandlerLoop();
260
261 bool handleNextRequest();
262 void handleSDOUpdateRequest(const std::shared_ptr<SDOUpdateRequest>& request);
263 void handleChangeStateRequest(const std::shared_ptr<ChangeStateRequest>& request);
264 void handleReadStatesRequest(const std::shared_ptr<ReadStatesRequest>& request);
265 void handleRegisterResetRequest(const std::shared_ptr<RegisterResetRequest>& request);
266 void handleRegisterReadRequest(const std::shared_ptr<RegisterReadRequest>& request);
267 };
268} // namespace armarx::control::ethercat
uint16_t slaveConfiguredAddress
uint8_t index
void deactivateCOECA(std::uint16_t slaveIndex)
This deactivates the Complete access mode in CoE for the given slave.
Definition BusIO.cpp:451
void setTimeouts(Timeouts const &timeouts)
Definition BusIO.cpp:470
bool readSDOByteBuffer(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, int *buflen, unsigned char *buf, bool completeAccess=false)
Performs a SDO read from the slave and returns true if it succeeds.
Definition BusIO.h:160
EtherCATState changeStateOfSlave(std::uint16_t slaveIndex, EtherCATState state, bool validate=true)
Definition BusIO.cpp:409
bool readSDOEntry(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, T &result, bool completeAccess=false)
Performs a SDO read of an single entry from the slave and returns true if it succeeds.
Definition BusIO.h:133
void rtUpdatePDO()
Updates the PDO of all slaves.
Definition BusIO.cpp:115
bool writeSDOByteBuffer(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, int buflen, const unsigned char *buf, bool completeAccess=false)
Performs a SDO write to the slave with the given slaveIndex and returns true if it succeeds.
Definition BusIO.h:106
bool readRegisters(std::vector< RegisterDataList > &registerData)
Definition BusIO.cpp:439
EtherCATState changeStateOfBus(EtherCATState state, bool validate=true)
Definition BusIO.cpp:417
bool resetErrorRegisters(std::uint16_t slaveIndex)
Definition BusIO.cpp:433
bool writeSDOEntry(std::uint16_t slaveIndex, std::uint16_t index, std::uint8_t subIndex, T value, bool completeAccess=false)
Performs a SDO write to a single entry to the slave with the give slaveIndex and returns true if it s...
Definition BusIO.h:79
std::array< char, 4096 > IOMap
IOmap the IO map where the process data are mapped in.
Definition BusIO.h:209
Brief description of class ChangeStateRequest.
Brief description of class ESIHandler.
Definition ESI.h:46
This class is a wrapper around an enum containing the different EtherCAT states.
Brief description of class ReadStatesRequest.
Brief description of class RegisterReadRequest.
Brief description of class RegisterResetRequest.
Brief description of class RequestQueue.
Brief description of class SDOUpdateRequest.
The EtherCATFrameList struct holds a list of EtherCAT frames that can be scheduled in round-robin-sty...
The EtherCATFrame struct represents an EtherCAT frame according to the EtherCAT spec.