25 #include "EdgeGrblDeviceBase.hpp"
33 #include <ccut/Regex.hpp>
34 #include <ccut/async.hpp>
37 #include <fmc_mfe/libfmc_mfe.h>
38 #include <logger/Logger.hpp>
43 #include "Exception.hpp"
45 using namespace logger;
46 using namespace std::chrono;
48 static const size_t s_edgeFifoTxSize{512};
49 static constexpr uint32_t s_edgeFifoTxNullCharMask{(uint32_t) (1 << 18)};
50 static constexpr uint32_t s_edgeFifoRxEmptyMask{(uint32_t) (1 << 8)};
51 static const std::chrono::milliseconds s_edgeFifoRxFreeTimeout{10};
55 const std::string EdgeGrblDeviceBase::loggerCat{
"edge:edgegrbldevice"};
57 EdgeGrblDeviceBase::EdgeGrblDeviceBase(
int lun,
const std::string &driverPath)
59 init(lun, driverPath);
62 EdgeGrblDeviceBase::EdgeGrblDeviceBase() {}
64 void EdgeGrblDeviceBase::init(
int lun,
const std::string &driverPath)
66 bool simMode{!driverPath.empty()};
68 drvOpen(lun, driverPath, simMode);
69 m_fifoBytes.resize(m_edgeDrvHdl->reg_map->grbl_fifo.tx_dr->reg_attr->depth);
72 EdgeGrblDeviceBase::read();
75 ::fcntl(m_wakeFd[0], F_SETFL, ::fcntl(m_wakeFd[0], F_GETFL, 0) | O_NONBLOCK);
76 ::fcntl(m_wakeFd[1], F_SETFL, ::fcntl(m_wakeFd[1], F_GETFL, 0) | O_NONBLOCK);
79 EdgeGrblDeviceBase::~EdgeGrblDeviceBase()
86 void EdgeGrblDeviceBase::read()
89 struct edge_reg *txCntReg = m_edgeDrvHdl->reg_map->grbl_fifo.tx_counter;
90 if (edge_get(m_edgeDrvHdl->edge_hdl, txCntReg, &txCnt, 1))
92 error(loggerCat) <<
"Failed getting tx_counter register";
94 std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)}};
98 if (!m_buffer.remaining())
100 error(loggerCat) <<
"flushing buffer";
104 struct edge_reg *txDataReg = m_edgeDrvHdl->reg_map->grbl_fifo.tx_dr;
105 size_t bytesToRead = std::min(m_buffer.remaining(),
106 static_cast<size_t>(txCnt));
107 m_fifoBytes.reserve(bytesToRead);
109 if (edge_get(m_edgeDrvHdl->edge_hdl, txDataReg, m_fifoBytes.data(),
110 static_cast<uint32_t
>(bytesToRead)))
112 error(loggerCat) <<
"Failed getting " << bytesToRead
113 <<
" bytes from tx_dr register";
115 smc::ErrorCode::InternalError,
116 std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)}};
120 for (
size_t i = 0; i < bytesToRead; ++i)
122 const char byte = *(m_fifoBytes.data() + i);
129 void EdgeGrblDeviceBase::write(
const std::string &data)
131 uint32_t rxByteCount;
132 if (edge_get(m_edgeDrvHdl->edge_hdl,
133 m_edgeDrvHdl->reg_map->grbl_fifo.rx_counter, &rxByteCount, 1))
135 error(loggerCat) <<
"Failed getting data from rx_count register";
137 std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)}};
139 struct edge_reg *rxDataReg = m_edgeDrvHdl->reg_map->grbl_fifo.rx_dr;
140 size_t rxFreeBytes = rxDataReg->reg_attr->depth - rxByteCount;
142 size_t bytesWritten = 0;
143 while (bytesWritten < data.size())
145 size_t bytesToWrite = std::min((data.size() - bytesWritten),
147 if (edge_set(m_edgeDrvHdl->edge_hdl, rxDataReg,
148 const_cast<void *
>(
reinterpret_cast<const void *
>(
149 data.c_str() + bytesWritten)),
152 error(loggerCat) <<
"Failed writing " << bytesToWrite
153 <<
" bytes to rx_dr register";
155 smc::ErrorCode::InternalError,
156 std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)}};
159 if ((bytesWritten = bytesToWrite) < data.size())
161 if (!waitIrq(s_edgeFifoRxFreeTimeout,
162 m_edgeDrvHdl->reg_map->grbl_fifo.intc_sr,
163 s_edgeFifoRxEmptyMask))
166 <<
"Failed waiting for Rx FIFO empty interrupt";
168 "Rx FIFO interrupt timeout"};
170 rxFreeBytes = rxDataReg->reg_attr->depth;
175 bool EdgeGrblDeviceBase::wait(
const std::chrono::milliseconds &timeout)
177 return waitIrq(timeout, m_edgeDrvHdl->reg_map->grbl_fifo.intc_sr,
178 s_edgeFifoTxNullCharMask);
181 void EdgeGrblDeviceBase::wake()
183 ::write(m_wakeFd[1],
"X", 1);
186 bool EdgeGrblDeviceBase::waitIrq(
const std::chrono::milliseconds &timeout,
187 const struct edge_reg *
const expectedReg,
188 uint32_t expectedBit)
190 struct pollfd pfds[2] = {{m_wakeFd[0], POLLIN, 0},
191 {m_edgeDrvHdl->edge_hdl->fd, POLLIN | POLLNVAL, 0}};
192 const steady_clock::time_point deadline = steady_clock::now() + timeout;
193 bool irqMatched{
false};
195 int remainingIrqs = 0;
198 while (!irqMatched && !waked)
200 milliseconds remaining = duration_cast<milliseconds>(
201 deadline - steady_clock::now());
202 if (remaining.count() < 0)
205 int res = ::poll(pfds, 2, remaining.count() + 1);
209 if (pfds[0].revents & POLLIN)
211 std::vector<char> buffer(10);
212 ::read(m_wakeFd[0], buffer.data(), buffer.size());
217 if (pfds[1].revents & POLLIN)
220 if (edge_wait_irq(m_edgeDrvHdl->edge_hdl, &irqRes) < 0)
223 <<
"edge_wait_irq failed: " << ::strerror(errno);
224 throw make_errno_exception(smc::ErrorCode::IO);
227 remainingIrqs = irqRes.queued;
229 if ((irqRes.irq_src == expectedReg) &&
230 (irqRes.irq_value & expectedBit))
234 if (pfds[1].revents & POLLNVAL)
236 error(loggerCat) <<
"IRQ poll() failed - wrong poll request";
238 "IRQ poll() failed - wrong poll request");
249 error(loggerCat) <<
"poll() failed waiting for IRQ";
251 "IRQ poll() failed");
256 while (remainingIrqs--)
258 if (edge_wait_irq(m_edgeDrvHdl->edge_hdl, &irqRes) < 0)
261 <<
"edge_wait_irq (flush) failed: " << ::strerror(errno);
268 void EdgeGrblDeviceBase::read(
struct edge_reg *reg,
274 err =
"driver not initialized";
275 else if (reg && reg->reg_attr->dwidth != 32)
276 err =
"invalid register size";
277 else if (edge_get_range(m_edgeDrvHdl->edge_hdl, reg, offset, &value, 1) != 0)
278 err = edge_strerror(m_edgeDrvHdl->edge_hdl);
282 err =
"Failed to read register: " + err;
283 error(loggerCat) << err;
288 void EdgeGrblDeviceBase::read(
struct edge_reg *reg,
289 std::vector<uint32_t> &values)
293 err =
"driver not initialized";
294 else if (reg && reg->reg_attr->dwidth != 32)
295 err =
"invalid register size";
296 else if (edge_get_range(m_edgeDrvHdl->edge_hdl, reg, 0, values.data(),
298 err = edge_strerror(m_edgeDrvHdl->edge_hdl);
302 err =
"Failed to read register: " + err;
303 error(loggerCat) << err;
308 void EdgeGrblDeviceBase::write(
struct edge_reg *reg,
314 err =
"driver not initialized";
315 else if (reg && reg->reg_attr->dwidth != 32)
316 err =
"invalid register size";
317 else if (edge_set_range(m_edgeDrvHdl->edge_hdl, reg, offset, &value, 1) != 0)
318 err = edge_strerror(m_edgeDrvHdl->edge_hdl);
322 err =
"Failed to write register: " + err;
323 error(loggerCat) << err;
328 void EdgeGrblDeviceBase::drvOpen(
int lun,
const std::string &simPath,
bool isSim)
335 void *lib = dlopen((simPath +
"/libfmc_mfe_sim.so").c_str(),
336 RTLD_LAZY | RTLD_NODELETE);
340 m_edgeDrvHdl = fmc_mfe_sim_open(lun, simPath.c_str());
344 m_edgeDrvHdl = fmc_mfe_drv_open(lun);
347 if (m_edgeDrvHdl == NULL)
349 error(loggerCat) <<
"Opening fmc_mfe driver failed: "
350 << std::string{edge_strerror(NULL)};
352 std::string{edge_strerror(NULL)});
355 struct edge_vers version;
356 if (edge_get_version(m_edgeDrvHdl->edge_hdl, &version) == 0)
357 info(loggerCat) <<
"fmc_mfe: " << version.hw_lif_vers;
359 error(loggerCat) <<
"Failed to retrieve driver version";
362 struct edge_irq_cfg cfg;
363 cfg.irq_src_reg = m_edgeDrvHdl->reg_map->grbl_fifo.intc_sr;
364 cfg.irq_mask = s_edgeFifoTxNullCharMask | s_edgeFifoRxEmptyMask;
370 if (edge_set_irq_cfg(m_edgeDrvHdl->edge_hdl, &cfg,
371 EDGE_IRQ_SRC | EDGE_IRQ_MASK | EDGE_IRQ_QUEUE |
374 error(loggerCat) <<
"Enabling IRQ queue in edge failed: "
375 << std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)};
377 std::string{edge_strerror(m_edgeDrvHdl->edge_hdl)});
382 <<
"fmc_mfe driver opened in sim mode on path " << simPath;
384 notice(loggerCat) <<
"fmc_mfe driver opened";
387 void EdgeGrblDeviceBase::drvClose()
389 if (m_edgeDrvHdl != NULL)
391 fmc_mfe_close(m_edgeDrvHdl);
392 notice(loggerCat) <<
"fmc_mfe driver closed";
Exception thrown by MotionController in case of issues with command.