81 void OnCsInd(
COLSS*, uint8_t cs) noexcept;
82 void OnErrInd(
COLSS*, uint8_t cs, uint8_t err, uint8_t spec) noexcept;
83 void OnLssIdInd(
COLSS*, uint8_t cs, co_unsigned32_t
id) noexcept;
84 void OnNidInd(
COLSS*, uint8_t cs, uint8_t
id) noexcept;
85 void OnScanInd(
COLSS*, uint8_t cs,
const co_id*
id) noexcept;
87 void OnWait(::std::error_code) noexcept;
103 void* lss_data{
nullptr};
109 co_id id1{4, 0, 0, 0, 0};
110 co_id id2{4, 0, 0, 0, 0};
116 LssSwitchRequestBase::OnRequest(
void* data) noexcept {
121 LssSwitchSelectiveRequestBase::OnRequest(
void* data) noexcept {
126 LssSetIdRequestBase::OnRequest(
void* data) noexcept {
131 LssSetBitrateRequestBase::OnRequest(
void* data) noexcept {
136 LssSwitchBitrateRequestBase::OnRequest(
void* data) noexcept {
141 LssStoreRequestBase::OnRequest(
void* data) noexcept {
146 LssGetVendorIdRequestBase::OnRequest(
void* data) noexcept {
151 LssGetProductCodeRequestBase::OnRequest(
void* data) noexcept {
156 LssGetRevisionRequestBase::OnRequest(
void* data) noexcept {
161 LssGetSerialNrRequestBase::OnRequest(
void* data) noexcept {
166 LssGetIdRequestBase::OnRequest(
void* data) noexcept {
171 LssIdNonConfigRequestBase::OnRequest(
void* data) noexcept {
176 LssSlowscanRequestBase::OnRequest(
void* data) noexcept {
181 LssFastscanRequestBase::OnRequest(
void* data) noexcept {
188 : impl_(new
Impl_(this, exec, node, ctrl, node.nmt())) {}
190 LssMaster::~LssMaster() =
default;
207 ::std::chrono::microseconds
209 ::std::lock_guard<Impl_>
lock(*impl_);
210 ::std::chrono::microseconds::rep value = impl_->inhibit;
211 return ::std::chrono::microseconds(value * 100);
216 auto value = inhibit.count();
218 if (value > ::std::numeric_limits<uint16_t>::max() * 100)
219 value = ::std::numeric_limits<uint16_t>::max() * 100;
221 ::std::lock_guard<Impl_>
lock(*impl_);
223 impl_->inhibit = (value + 99) / 100;
224 if (impl_->lss) impl_->lss->setInhibit(impl_->inhibit);
228 ::std::chrono::milliseconds
230 ::std::lock_guard<Impl_>
lock(*impl_);
231 return ::std::chrono::milliseconds(impl_->timeout);
236 auto value = timeout.count();
238 if (value > ::std::numeric_limits<int>::max())
239 value = ::std::numeric_limits<int>::max();
241 ::std::lock_guard<Impl_>
lock(*impl_);
242 impl_->timeout = value;
243 if (impl_->lss) impl_->lss->setTimeout(impl_->timeout);
253 p.
set(ec ? ::std::make_exception_ptr(
254 ::std::system_error(ec,
"AsyncSwitch"))
257 if (preq) *preq = req;
267 exec, address, [p](::std::error_code ec)
mutable {
268 p.
set(ec ? ::std::make_exception_ptr(
269 ::std::system_error(ec,
"AsyncSwitchSelective"))
272 if (preq) *preq = req;
283 p.
set(ec ? ::std::make_exception_ptr(
284 ::std::system_error(ec,
"AsyncSetId"))
287 if (preq) *preq = req;
297 exec, bitrate, [p](::std::error_code ec)
mutable {
298 p.
set(ec ? ::std::make_exception_ptr(
299 ::std::system_error(ec,
"AsyncSetBitrate"))
302 if (preq) *preq = req;
311 p.
set(ec ? ::std::make_exception_ptr(::std::system_error(ec,
"AsyncStore"))
314 if (preq) *preq = req;
324 exec, [p](::std::error_code ec, uint32_t number)
mutable {
326 p.
set(util::failure(::std::make_exception_ptr(
327 ::std::system_error(ec,
"AsyncGetVendorId"))));
329 p.
set(util::success(number));
331 if (preq) *preq = req;
341 exec, [p](::std::error_code ec, uint32_t number)
mutable {
343 p.
set(util::failure(::std::make_exception_ptr(
344 ::std::system_error(ec,
"AsyncGetProductCode"))));
346 p.
set(util::success(number));
348 if (preq) *preq = req;
358 exec, [p](::std::error_code ec, uint32_t number)
mutable {
360 p.
set(util::failure(::std::make_exception_ptr(
361 ::std::system_error(ec,
"AsyncGetRevision"))));
363 p.
set(util::success(number));
365 if (preq) *preq = req;
375 exec, [p](::std::error_code ec, uint32_t number)
mutable {
377 p.
set(util::failure(::std::make_exception_ptr(
378 ::std::system_error(ec,
"AsyncGetSerialNr"))));
380 p.
set(util::success(number));
382 if (preq) *preq = req;
391 exec, [p](::std::error_code ec, uint8_t
id)
mutable {
393 p.
set(util::failure(::std::make_exception_ptr(
394 ::std::system_error(ec,
"AsyncGetId"))));
396 p.
set(util::success(
id));
398 if (preq) *preq = req;
408 exec, [p](::std::error_code ec,
bool found)
mutable {
410 p.
set(util::failure(::std::make_exception_ptr(
411 ::std::system_error(ec,
"AsyncIdNonConfig"))));
413 p.
set(util::success(found));
415 if (preq) *preq = req;
427 [p](::std::error_code ec,
const LssAddress& address)
mutable {
429 p.
set(util::failure(::std::make_exception_ptr(
430 ::std::system_error(ec,
"AsyncSlowscan"))));
432 p.
set(util::success(address));
434 if (preq) *preq = req;
446 [p](::std::error_code ec,
const LssAddress& address)
mutable {
448 p.
set(util::failure(::std::make_exception_ptr(
449 ::std::system_error(ec,
"AsyncFastscan"))));
451 p.
set(util::success(address));
453 if (preq) *preq = req;
460 ::std::lock_guard<util::BasicLockable>
lock(*
this);
467 ::std::lock_guard<Impl_>
lock(*impl_);
468 return impl_->Cancel(&req, ec) != 0;
474 ::std::lock_guard<Impl_>
lock(*impl_);
475 return impl_->Cancel(
nullptr, ec);
480 ::std::lock_guard<Impl_>
lock(*impl_);
481 return impl_->Abort(&req) != 0;
486 ::std::lock_guard<Impl_>
lock(*impl_);
487 return impl_->Abort(
nullptr);
492 int bitrate, ::std::chrono::milliseconds delay,
493 ::std::function<
void(::std::error_code ec)> res) noexcept {
520 ::std::error_code ec;
526 }
catch (::std::system_error& e) {
556 exec(exec_ ? exec_ : static_cast<ev_exec_t*>(node.GetExecutor())),
561 nmt->getLSSReq(&lss_func, &lss_data);
562 nmt->setLSSReq<
Impl_, &Impl_::OnLssReq>(
this);
565 inhibit = lss->getInhibit();
566 timeout = lss->getTimeout();
573 ::std::error_code ec;
574 ctrl->get_bitrate(&bitrate,
nullptr, ec);
578 LssMaster::Impl_::~Impl_() { nmt->setLSSReq(lss_func, lss_data); }
581 LssMaster::Impl_::OnLssReq(
CONMT*,
COLSS* lss) noexcept {
584 lss->setInhibit(inhibit);
585 lss->setTimeout(timeout);
589 self->GetExecutor().post([
this]() noexcept {
590 self->OnStart([
this](::std::error_code) noexcept {
591 ::std::lock_guard<Impl_>
lock(*
this);
600 if (!req.
exec) req.
exec =
self->GetExecutor();
606 if (first) OnRequest(req);
629 n += n < ::std::numeric_limits<::std::size_t>::max();
662 return req !=
nullptr;
672 ::std::error_code ec;
673 if (!lss->switchReq(static_cast<int>(req.
state)))
683 LssMaster::Impl_::OnSwitchSelective(
696 if (lss->switchSelReq<
Impl_, &Impl_::OnCsInd>(id1,
this) == -1) {
714 if (lss->setIdReq<
Impl_, &Impl_::OnErrInd>(req.
id,
this) == -1) {
741 if (lss->setRateReq<
Impl_, &Impl_::OnErrInd>(req.
bitrate / 1000,
this) ==
758 LssMaster::Impl_::OnSwitchBitrate(
768 if (!bitrate || req.
delay < 0 ||
769 req.
delay > ::std::numeric_limits<uint16_t>::max()) {
772 }
else if (lss->switchRateReq(req.
delay) == -1) {
779 ::std::chrono::milliseconds delay(req.
delay);
781 self->GetExecutor().post([
this, delay]() noexcept {
782 self->OnSwitchBitrate(bitrate, delay, [
this](::std::error_code ec) {
784 ::std::lock_guard<Impl_>
lock(*
this);
807 if (lss->storeReq<
Impl_, &Impl_::OnErrInd>(
this) == -1) {
816 LssMaster::Impl_::OnGetVendorId(
827 if (lss->getVendorIdReq<
Impl_, &Impl_::OnLssIdInd>(
this) == -1) {
836 LssMaster::Impl_::OnGetProductCode(
847 if (lss->getProductCodeReq<
Impl_, &Impl_::OnLssIdInd>(
this) == -1) {
856 LssMaster::Impl_::OnGetRevision(
867 if (lss->getRevisionReq<
Impl_, &Impl_::OnLssIdInd>(
this) == -1) {
876 LssMaster::Impl_::OnGetSerialNr(
887 if (lss->getSerialNrReq<
Impl_, &Impl_::OnLssIdInd>(
this) == -1) {
906 if (lss->getIdReq<
Impl_, &Impl_::OnNidInd>(
this) == -1) {
915 LssMaster::Impl_::OnIdNonConfig(
925 if (lss->idNonCfgSlaveReq<
Impl_, &Impl_::OnCsInd>(
this) == -1) {
949 if (lss->slowscanReq<
Impl_, &Impl_::OnScanInd>(id1, id2,
this) == -1) {
972 if (lss->fastscanReq<
Impl_, &Impl_::OnScanInd>(&id1, &id2,
this) == -1) {
981 LssMaster::Impl_::OnCsInd(
COLSS*, uint8_t cs) noexcept {
995 LssMaster::Impl_::OnErrInd(
COLSS*, uint8_t cs, uint8_t err, uint8_t) noexcept {
1045 LssMaster::Impl_::OnLssIdInd(
COLSS*, uint8_t cs, co_unsigned32_t
id) noexcept {
1061 LssMaster::Impl_::OnNidInd(
COLSS*, uint8_t cs, uint8_t
id) noexcept {
1077 LssMaster::Impl_::OnScanInd(
COLSS*, uint8_t cs,
const co_id*
id) noexcept {
1099 req.OnRequest(
this);
1113 exec.on_task_fini();
1116 if (task) OnRequest(*static_cast<detail::LssRequestBase*>(task));
LssFuture< void > AsyncSwitch(ev_exec_t *exec, LssState state=LssState::WAITING, detail::LssSwitchRequestBase **preq=nullptr)
Queues an asynchronous LSS 'switch state global' request and creates a future which becomes ready onc...
void set_bitrate(int nominal, int data, ::std::error_code &ec) noexcept
LssFuture< uint32_t > AsyncGetSerialNr(ev_exec_t *exec, detail::LssGetSerialNrRequestBase **preq=nullptr)
Queues an asynchronous LSS 'inquire identity serial-number' request and creates a future which become...
const struct ev_exec_vtbl *const ev_exec_t
An abstract task executor.
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
void stop(::std::error_code &ec) noexcept
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, uint32_t >::value, detail::LssGetSerialNrRequestWrapper< F > * >::type make_lss_get_serial_nr_request(ev_exec_t *exec, F &&con)
Creates an LSS 'inquire identity serial-number' request with a completion task.
void co_nmt_lss_req_t(co_nmt_t *nmt, co_lss_t *lss, void *data)
The type of a CANopen LSS request function, invoked by an NMT master before booting the slaves (see F...
::std::error_code ec
The error code (0 on success).
This is the internal header file of the C++ CANopen application library.
size_t ev_task_queue_abort(struct sllist *queue)
Aborts the tasks in queue by invoking ev_exec_on_task_fini() for each of them.
void post(ev_task &task) noexcept
LssFuture< void > AsyncSwitchSelective(ev_exec_t *exec, const LssAddress &address, detail::LssSwitchSelectiveRequestBase **preq=nullptr)
Queues an asynchronous LSS 'switch state selective' request and creates a future which becomes ready ...
LssFuture< void > AsyncStore(ev_exec_t *exec, detail::LssStoreRequestBase **preq=nullptr)
Queues an asynchronous LSS 'store configuration' request and creates a future which becomes ready onc...
void sllist_push_front(struct sllist *list, struct slnode *node)
Pushes a node to the front of a singly-linked list.
LssFuture< LssAddress > AsyncFastscan(ev_exec_t *exec, const LssAddress &address={0, 0, 0, 0}, const LssAddress &mask={0, 0, 0, 0}, detail::LssFastscanRequestBase **preq=nullptr)
Queues an asynchronous 'LSS Fastscan' request and creates a future which becomes ready once the reque...
void unlock() final
Releases the lock held by the execution agent. Throws no exceptions.
void SetTime()
Update the CAN network time.
LssFuture< LssAddress > AsyncSlowscan(ev_exec_t *exec, const LssAddress &lo, const LssAddress &hi, detail::LssSlowscanRequestBase **preq=nullptr)
Queues an asynchronous 'LSS Slowscan' request and creates a future which becomes ready once the reque...
#define LELY_CO_LSS_TIMEOUT
The default LSS timeout (in milliseconds).
A node in a singly-linked list.
The base class for CANopen LSS masters.
struct slnode * sllist_pop_front(struct sllist *list)
Pops a node from the front of a singly-linked list.
struct sllist * sllist_append(struct sllist *dst, struct sllist *src)
Appends the singly-linked list at src to the one at dst.
struct slnode * sllist_first(const struct sllist *list)
Returns a pointer to the first node in a singly-linked list.
void SetInhibit(const ::std::chrono::microseconds &inhibit)
Sets the inhibit time between successive CAN frames.
bool Abort(detail::LssRequestBase &req)
Aborts a pending LSS request.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::LssSetIdRequestWrapper< F > * >::type make_lss_set_id_request(ev_exec_t *exec, uint8_t id, F &&con)
Creates an LSS 'configure node-ID' request with a completion task.
uint32_t revision
The revision number.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::LssSetBitrateRequestWrapper< F > * >::type make_lss_set_bitrate_request(ev_exec_t *exec, int bitrate, F &&con)
Creates an LSS 'configure bit timing parameters' request with a completion task.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::LssSwitchSelectiveRequestWrapper< F > * >::type make_lss_switch_selective_request(ev_exec_t *exec, const LssAddress &address, F &&con)
Creates an LSS 'switch state selective' request with a completion task.
An opaque CANopen LSS master/slave service type.
struct slnode * sllist_remove(struct sllist *list, struct slnode *node)
Removes a node from a singly-linked list.
void on_task_init() noexcept
int bitrate
The requested pending bit rate (in bit/s) of the LSS slave device.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, uint32_t >::value, detail::LssGetProductCodeRequestWrapper< F > * >::type make_lss_get_product_code_request(ev_exec_t *exec, F &&con)
Creates an LSS 'inquire identity product-code' request with a completion task.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
::std::size_t CancelAll()
Cancels all pending LSS requests and stops the ongoing request, if any.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::LssStoreRequestWrapper< F > * >::type make_lss_store_request(ev_exec_t *exec, F &&con)
Creates an LSS 'store configuration' request with a completion task.
This header file is part of the C++ CANopen application library; it contains the CANopen Layer Settin...
This header file is part of the CANopen library; it contains the C++ interface of the network managem...
void sllist_push_back(struct sllist *list, struct slnode *node)
Pushes a node to the back of a singly-linked list.
bool Cancel(detail::LssRequestBase &req)
Cancels a pending LSS request.
uint32_t product_code
THe product code.
void restart(::std::error_code &ec) noexcept
LssAddress lo
The lower bound of the LSS address of the slave device.
uint8_t id
The active node-ID reported by the LSS slave device.
uint32_t serial_nr
THe serial number.
LssFuture< uint32_t > AsyncGetVendorId(ev_exec_t *exec, detail::LssGetVendorIdRequestBase **preq=nullptr)
Queues an asynchronous LSS 'inquire identity vendor-ID' request and creates a future which becomes re...
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
ev_exec_t * exec
A pointer to the executor to which the task is (to be) submitted.
void SetTime()
Updates the CAN network time.
Future< T, E > get_future() const noexcept
Returns a lely::ev::Future with (a reference to) the same shared state as *this.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, LssAddress >::value, detail::LssSlowscanRequestWrapper< F > * >::type make_lss_slowscan_request(ev_exec_t *exec, const LssAddress &lo, const LssAddress &hi, F &&con)
Creates an 'LSS Slowscan' request with a completion task.
LssAddress hi
The upper bound of the LSS address of the slave device.
The 128-bit number uniquely identifying each CANopen node.
void Submit(detail::LssRequestBase &req)
Queues an LSS request.
An abstract interface conforming to the BasicLockable concept.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, uint8_t >::value, detail::LssGetIdRequestWrapper< F > * >::type make_lss_get_id_request(ev_exec_t *exec, F &&con)
Creates an LSS 'inquire node-ID' request with a completion task.
::std::size_t AbortAll()
Aborts all pending LSS requests.
LssFuture< uint8_t > AsyncGetId(ev_exec_t *exec, detail::LssGetIdRequestBase **preq=nullptr)
Queues an asynchronous LSS 'inquire node-ID' request and creates a future which becomes ready once th...
ev::Executor GetExecutor() const noexcept
Returns the default executor used to execute completion tasks of LSS requests.
ev::Executor GetExecutor() const noexcept
Returns the executor to which the completion task is (to be) submitted.
::std::chrono::microseconds GetInhibit() const
Returns the inhibit time between successive CAN frames.
io::CanControllerBase * GetController() const noexcept
Returns the pointer to the CAN controller for this node passed to the constructor (may be a null poin...
Node & GetNode() const noexcept
Returns the CANopen master node.
LssMaster(ev_exec_t *exec, Node &node, io::CanControllerBase *ctrl=nullptr)
Creates a new CANopen LSS master.
void unlock() final
Releases the lock held by the execution agent. Throws no exceptions.
LssFuture< void > AsyncSetId(ev_exec_t *exec, uint8_t id, detail::LssSetIdRequestBase **preq=nullptr)
Queues an asynchronous LSS 'configure node-ID' request and creates a future which becomes ready once ...
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, uint32_t >::value, detail::LssGetVendorIdRequestWrapper< F > * >::type make_lss_get_vendor_id_request(ev_exec_t *exec, F &&con)
Creates an LSS 'inquire identity vendor-ID' request with a completion task.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, bool >::value, detail::LssIdNonConfigRequestWrapper< F > * >::type make_lss_id_non_config_request(ev_exec_t *exec, F &&con)
Creates an LSS 'identify non-configured remote slave' request with a completion task.
int sllist_empty(const struct sllist *list)
Returns 1 if the singly-linked list is empty, and 0 if not.
An abstract task executor. This class is a wrapper around ev_exec_t*.
void unlock() final
Releases the lock held by the execution agent. Throws no exceptions.
void SetTimeout(const ::std::chrono::milliseconds &timeout)
Sets the timeout when waiting for a slave to respond to an LSS request.
int delay
The delay (in milliseconds) before and after the switch, during which CAN frames MUST NOT be sent...
LssAddress mask
A mask specifying which bits in the LSS address of the slave device are already known and can be skip...
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, LssAddress >::value, detail::LssFastscanRequestWrapper< F > * >::type make_lss_fastscan_request(ev_exec_t *exec, const LssAddress &address, const LssAddress &mask, F &&con)
Creates an 'LSS Fastscan' request with a completion task.
result_type & get()
Returns the result of a ready future.
void lock() final
Blocks until a lock can be obtained for the current execution agent (thread, process, task).
uint8_t id
The requested pending node-ID of the LSS slave device.
This header file is part of the CANopen library; it contains the C++ interface of the Layer Setting S...
LssFuture< bool > AsyncIdNonConfig(ev_exec_t *exec, detail::LssIdNonConfigRequestBase **preq=nullptr)
Queues an asynchronous LSS 'identify non-configured remote slave' request and creates a future which ...
struct ev_task * ev_task_from_node(struct slnode *node)
Converts a pointer to a node in a queue to the address of the task containing the node...
::std::error_code make_error_code(SdoErrc e) noexcept
Creates an error code corresponding to an SDO abort code.
An opaque CANopen NMT master/slave service type.
LssState
The states of the LSS finite state automaton (FSA) of a slave device.
uint32_t vendor_id
The vendor-ID.
ev::Future< void, ::std::exception_ptr > AsyncWait(ev_exec_t *exec, const time_point &t, io_tqueue_wait **pwait=nullptr)
Submits an asynchronous wait operation and creates a future which becomes ready once the wait operati...
LssFuture< void > AsyncSetBitrate(ev_exec_t *exec, int bitrate, detail::LssSetBitrateRequestBase **preq=nullptr)
Queues an asynchronous LSS 'configure bit timing parameters' request and creates a future which becom...
A reference to an abstract CAN controller.
void sllist_init(struct sllist *list)
Initializes a singly-linked list.
LssFuture< uint32_t > AsyncGetRevision(ev_exec_t *exec, detail::LssGetRevisionRequestBase **preq=nullptr)
Queues an asynchronous LSS 'inquire identity revision-number' request and creates a future which beco...
uint32_t number
The LSS number reported by the slave device.
::std::chrono::milliseconds GetTimeout() const
Returns the timeout when waiting for a slave to respond to an LSS request.
The base class for CANopen nodes.
LssState state
The desired state of the LSS slave devices.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code, uint32_t >::value, detail::LssGetRevisionRequestWrapper< F > * >::type make_lss_get_revision_request(ev_exec_t *exec, F &&con)
Creates an LSS 'inquire identity revision-number' request with a completion task. ...
virtual void OnSwitchBitrate(int bitrate, ::std::chrono::milliseconds delay, ::std::function< void(::std::error_code ec)> res) noexcept
The function invoked when the master activates the bit rate of all CANopen devices in the network...
bool set(U &&u)
Satisfies a promise, if it was not aready satisfied, and stores the specified value as the result in ...
#define LELY_CO_LSS_INHIBIT
The default LSS inhibit time (in multiples of 100 microseconds).
LssAddress address
On success, the LSS address of the detected slave device.
typename ::std::enable_if< compat::is_invocable< F, ::std::error_code >::value, detail::LssSwitchRequestWrapper< F > * >::type make_lss_switch_request(ev_exec_t *exec, LssState state, F &&con)
Creates an LSS 'switch state global' request with a completion task.
LssAddress address
The address of the LSS slave device to be switched into the configuration state.
LssFuture< uint32_t > AsyncGetProductCode(ev_exec_t *exec, detail::LssGetProductCodeRequestBase **preq=nullptr)
Queues an asynchronous LSS 'inquire identity product-code' request and creates a future which becomes...