Skip to content

ICanOpenSafety Interface

CANopen Safety (CiA DSP 304 V1.0) on a node: the SRDOs it produces and consumes, the global failsafe command, and — for a master or tool — the configuration and verification of a peer's safety parameters, run as the configuration entity of CiA 319 v2.0.0 (identity verification, the configuration steps, the storage, the checksum of an SRVT the peer does not implement). Reached through Safety(this ICanOpenNode). A node has SRDOs only when opened with SrdoCount > 0 or a device description that declares them.

public interface ICanOpenSafety

Remarks

This library is not developed to IEC 61508 / DIN V VDE 0801 and claims no safety integrity level. It implements the data transport of DSP 304 V1.0 — the frame pair, the timing checks, the objects, the checksum — and leaves the diverse redundancy of §9.5 ("built by two different ways", "compared … in the application") and the safe state to the device.

Properties

ICanOpenSafety.SrdoCount Property

The number of SRDO records this node holds (0..64).

int SrdoCount { get; }

Property Value

Int32

Methods

ICanOpenSafety.CommitSafetyConfiguration() Method

§9.2 for a locally configured node: writes 13FFh:n for every record and then 13FEh = A5h. Until this is called the configuration is not valid and no SRDO runs in Operational.

void CommitSafetyConfiguration();

ICanOpenSafety.ConfigurePeerSafetyAsync(byte, PeerSafetyConfiguration, CancellationToken) Method

The configuration entity of CiA 319 v2.0.0 clause 5 on the §9.2 Figure 9 transaction. First the peer's identity (CiA 319 §5.2): 1018h:01, :02 and :03 are uploaded and compared with the bound description's own 1018h:01–03 — "the entries in the EDS" — as declared (ParameterValue, DefaultValue where none); a difference ends the call with those entries as the mismatches, and nothing is written. §5.2 requires all three of an SRD, where CiA 301 makes :02 and :03 optional: the file must declare them with a value, and the peer must implement them — one that aborts an upload of them is not an SRD this procedure can configure, and the abort propagates, unless an earlier entry already differed, when it is reported as a mismatch with no bytes read. The file's [DeviceInfo] numbers, where set, must agree with its 1018h entries; a file that contradicts itself, or whose three entries are all 0, describes no device and is refused before the first frame. Every transfer the call makes whatever the peer answers — the identity, 13FFh:00, 1300h, the checksums of the SRDOs named, 13FEh, the 1010h sub-index asked for — passes the peer-SDO gate before the first frame; the transfers that depend on the peer's count — sub-index 01h of every record up to it and every 13FFh:n, for the SRDOs the configuration does not name too — pass it once 13FFh:00 is read, before the first write, and a count above the bound description's highest SRDO record is refused there, since the gate could let no record above it through. Then (§5.3 step 1) it downloads 1300h, every record (deleted first, created last) and the checksums 13FFh:n, (step 2) reads everything back and compares byte for byte, and only then (step 3) writes 13FEh = A5h and reads it back — step 4 is the peer's own check of the checksums, and a peer that found one wrong answers that readback with 0. When Storage asks for it (step 5), the "save" signature is then downloaded to 1010h at that sub-index, so the acknowledged configuration outlasts the peer's reset; a store the peer aborts is reported in the result (StorageAbort), the acknowledgement standing. A tx SRDO whose communication record the bound description declares without sub-index 3 is one the peer is taken not to hold an SRVT for (CiA 319 §6.2): the configuration must say 20 ms there — the value such a peer checksums — and the sub-index is written and read back all the same, so that a peer which does hold it ends with 20 ms rather than a value from an earlier configuration (a delete writes sub-index 1 only); a peer that aborts the write with 0609 0011h (sub-index does not exist) does not implement it and is not asked to read it back, one that aborts it with 0601 0002h (read-only) holds it and is. A sub-index 3 the description declares read-only is not written, only read back; the configuration must say 20 ms there too. Before the first frame, every mapping entry is checked against the peer's bound EDS/DCF (declared, mappable, of a fixed width equal to the entry's, access in the SRDO's direction), since the deletion comes first. Every transfer passes the peer-SDO gate. The peer's SDO channel is reserved for the whole transaction: it waits for a call to that peer already in flight, and a concurrent SDO call of this node to that peer is refused as already in flight. The transaction works from the description and the configuration as they were when it started — when it owns the peer's channel, after any call it waited for: its pre-check, the gate of every transfer, the identity, the writes and the readback use copies taken then, not the bound description or the caller's configuration. A rebind, an unbind or an edit in place of either before that moment is seen; one after it takes effect for the next call, not half-way through this one. An SDO abort, a timeout or a gate refusal propagates as from SdoDownloadAsync; one from the step-5 store comes after the acknowledgement, which the peer then holds unstored. The peer's 13FEh is 0 once at least one parameter write has been accepted, because every such write clears it; an abort before that — for example 0800 0022h from an Operational peer, which refuses the first write — leaves it unchanged.

System.Threading.Tasks.Task<CanKit.Pro.CANopen.Safety.PeerSafetyResult> ConfigurePeerSafetyAsync(byte peerNodeId, CanKit.Pro.CANopen.Safety.PeerSafetyConfiguration configuration, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

peerNodeId Byte

configuration PeerSafetyConfiguration

cancellationToken CancellationToken

Returns

Task<PeerSafetyResult>

Exceptions

PeerSdoAccessException
No description is bound for the peer (the exception names 1018h:01, the first transfer, which has nothing to be compared with), or the bound description does not declare one of the transfers the call makes whatever the peer answers — 1018h:01–03, 13FFh:00, 1300h, 13FFh:n of an SRDO named, 13FEh, the 1010h sub-index Storage names — refused before the first frame by the gate that would refuse the transfer; or, once the count is read, sub-index 01h of a record up to it or 13FFh:n of an SRDO the configuration does not name — refused before the first write, likewise.

InvalidOperationException
The bound description declares a 1018h entry without a value this implementation reads (a plain number; a $NODEID formula is no identity), contradicts itself (a [DeviceInfo] number set and unlike its 1018h entry) or has 1018h:01–03 all 0, so it carries no identity to verify the peer against (CiA 319 §5.2) — refused before the first frame; or the peer's 13FFh:00 is not exactly one byte (it is UNSIGNED8; none, two or four bytes are refused, a longer one is not cut to its low byte), or the count is above 64 (§8.4.2.2) or above the bound description's highest SRDO record (the gate implies no record above it, so the SRDOs the peer has beyond the file could not be deleted) — refused before any further frame, nothing written; or the bound description declares ro or const a pair the configuration downloads — 13FFh:n, 13FEh, 1300h, a record entry, the 1010h sub-index asked for — which a peer honouring its file refuses with 0601 0002h: refused before the first frame, or for an SRDO the configuration does not name once the count is read, before the first write. A sub-index 3 declared read-only is no download (above).

ArgumentException
The configuration names an SRDO above the peer's count, or maps an object the peer's bound EDS/DCF does not declare, does not flag mappable, declares with another width or with a type without a fixed width (a string, a domain: an SRDO maps fixed-width objects only, this implementation's rule) or without a type this implementation knows (no DataType, or an unknown code: its width cannot be known), or does not make accessible in the SRDO's direction — checked before the first frame, because §9.2 deletes every SRDO of the peer first; or gives a tx SRDO whose record the description declares without a writable sub-index 3 an SRVT other than 20 ms (CiA 319 §6.2). What only the peer can judge stays the peer's.

ICanOpenSafety.ConfigureSrdoConsumer(int, SrdoMapping, TimeSpan, TimeSpan, Nullable<uint>, Nullable<uint>) Method

Writes record srdoNumber as a consumer: direction rx, SCT, SRVT, mapping and COB-IDs. See ConfigureSrdoProducer(int, SrdoMapping, TimeSpan, Nullable<uint>, Nullable<uint>) for the rest.

void ConfigureSrdoConsumer(int srdoNumber, CanKit.Pro.CANopen.Safety.SrdoMapping mapping, System.TimeSpan safeguardCycleTime, System.TimeSpan validationTime, System.Nullable<uint> cobId1=null, System.Nullable<uint> cobId2=null);

Parameters

srdoNumber Int32

mapping SrdoMapping

safeguardCycleTime TimeSpan

validationTime TimeSpan

cobId1 Nullable<UInt32>

cobId2 Nullable<UInt32>

ICanOpenSafety.ConfigureSrdoProducer(int, SrdoMapping, TimeSpan, Nullable<uint>, Nullable<uint>) Method

Writes record srdoNumber as a producer: direction tx, refresh time, the mapping (plain and inverted sub-indices), the COB-IDs — the pre-defined pair of Table 4 for SRDO 1 of a node-id ≤ 64 when none is given. The SRDO is deleted first and created last, as §8.4.2.2 requires for a mapping change. Writes 13FEh to 0; call CommitSafetyConfiguration() afterwards. The writes are checked whole before the first one: a configuration the dictionary would refuse part-way changes nothing.

void ConfigureSrdoProducer(int srdoNumber, CanKit.Pro.CANopen.Safety.SrdoMapping mapping, System.TimeSpan refreshTime, System.Nullable<uint> cobId1=null, System.Nullable<uint> cobId2=null);

Parameters

srdoNumber Int32

mapping SrdoMapping

refreshTime TimeSpan

cobId1 Nullable<UInt32>

cobId2 Nullable<UInt32>

Exceptions

InvalidOperationException
The node has no SRDOs, or is Operational (0800 0022h).

ArgumentOutOfRangeException
The number is not 1..SrdoCount, or a time is out of range.

ArgumentException
A value the dictionary refuses (the abort code is in the message; nothing is written) — among them a mapped object without a fixed width (a string or a domain, 0604 0041h: an SRDO maps fixed-width objects only, this implementation's rule) — or no COB-ID for a node-id above 64.

ICanOpenSafety.DeleteSrdo(int) Method

Sets the direction of the record to 0: the SRDO does not exist.

void DeleteSrdo(int srdoNumber);

Parameters

srdoNumber Int32

ICanOpenSafety.GetSrdoState(int) Method

The current validity of an SRDO: a snapshot of the actor's view. Right after the node is opened its records are taken on the actor's first turn, so a read before any call that round-trips the actor (State, say) has returned may still show None.

CanKit.Pro.CANopen.Safety.SrdoState GetSrdoState(int srdoNumber);

Parameters

srdoNumber Int32

Returns

SrdoState

Exceptions

ArgumentOutOfRangeException
The number is not 1..SrdoCount — on a node without SRDOs, every number.

ObjectDisposedException
The node has been disposed.

ICanOpenSafety.ObserveForeignSrdoAsync(byte, uint, ReadOnlyMemory<byte>, ReadOnlyMemory<byte>, CanOpenDeviceDescription, IForeignPdoSink, CancellationToken) Method

Splits an SRDO pair of another node into sink, like ObserveForeignPdoAsync(byte, uint, ReadOnlyMemory<byte>, CanOpenDeviceDescription, IForeignPdoSink, CancellationToken): the existing record whose live 1301h–1340h:05 equals cobId1 (the file is the fallback when the upload fails; a record whose direction is not 1 or 2, live or in the file, does not match: a deleted one may have kept the ids another SRDO now uses), the pair checked for equal length and bitwise inversion, the mapping read live from 1381h–13C0h or from the file — either only when each even sub-index up to the count repeats the odd one before it, the rule the device's own validator and loader apply (CiA DSP 304 §8.4.2.2, 1381h–13C0h); otherwise the pair is not decoded and the reason names the slot. A live even slot that was read and differs from its odd slot makes the pair not decoded, with no fallback to the file: live wins. A live slot that cannot be read, even or odd, means the live mapping is not read, and the file decides. Signals carry Srdo and the SRDO number. SRVT and SCT are the caller's to judge: it holds the timestamps. Nothing is written to this node's dictionary. The live mapping is read in full whenever its count is: the peer-SDO gate lets through every slot of an SRDO record the bound file implies, declared or not. A record whose COB-ID 1 word has a bit above bit 10 set, or a mapping with a dummy entry, is not decoded. The records searched are those peerDescription implies: up to its highest declared communication or mapping record, as the loader and the gate read it. The live reads of one observation are one snapshot of the peer: the peer's SDO channel is taken without waiting and held to the end, so a safety transaction that starts meanwhile waits for it and another SDO call of this node to that peer is refused as in flight; a channel busy at the start makes every live read of that observation "already in flight", and the whole snapshot is the file's.

System.Threading.Tasks.Task<CanKit.Pro.CANopen.Safety.ForeignSrdoObserveResult> ObserveForeignSrdoAsync(byte peerNodeId, uint cobId1, System.ReadOnlyMemory<byte> frame1, System.ReadOnlyMemory<byte> frame2, CanKit.Pro.CANopen.CanOpenDeviceDescription peerDescription, CanKit.Pro.CANopen.IForeignPdoSink sink, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

peerNodeId Byte

cobId1 UInt32

frame1 ReadOnlyMemory<Byte>

frame2 ReadOnlyMemory<Byte>

peerDescription CanOpenDeviceDescription

sink IForeignPdoSink

cancellationToken CancellationToken

Returns

Task<ForeignSrdoObserveResult>

ICanOpenSafety.SendGlobalFailsafeCommandAsync(CancellationToken) Method

Sends the global failsafe command (§8.2: COB-ID 001h, DLC 0). Requires Operational, and sets 1300h to 1 (EN 50325-5:2010 §6.4.2.1). The returned task is the send itself, not the node's actor turn that started it: it completes when the bus service confirmed the send — on its echo path once the echo arrived, otherwise once the driver accepted the frame — or reported its failure (on BackgroundExceptionOccurred, as for every frame), or when the send was cancelled. The send carries cancellationToken linked with the token of the Operational period: leaving Operational or disposing the node ends a send that has not reached the bus service's driver call quietly, the caller's cancellation ends it with OperationCanceledException; a frame the driver has been handed goes out (#294).

System.Threading.Tasks.Task SendGlobalFailsafeCommandAsync(System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

cancellationToken CancellationToken

Returns

Task

Exceptions

InvalidOperationException
The node is not Operational.

OperationCanceledException
cancellationToken was cancelled before the send was confirmed; or the bus service was disposed under the send, which is also reported on BackgroundExceptionOccurred as a transport failure.

CanOpenTransportException
LSS bit-rate switching suppresses transmission of the GFC; the command was not handed to the driver.

ICanOpenSafety.TriggerSrdoAsync(int, CancellationToken) Method

Transmits producer srdoNumber now (§8.1, event-driven) and restarts its refresh cycle. Nothing happens outside Operational.

System.Threading.Tasks.Task TriggerSrdoAsync(int srdoNumber, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

srdoNumber Int32

cancellationToken CancellationToken

Returns

Task

ICanOpenSafety.VerifyPeerSafetyConfigurationAsync(byte, PeerSafetyConfiguration, CancellationToken) Method

§8.3.1 step D: uploads 13FEh (must be A5h), 13FFh:n of every expected SRDO (must equal the checksum of the expected record) and the records themselves, and compares. An SRDO the expectation does not name must be deleted; its checksum is not compared, because the device checks only those of existing SRDOs (§9.5). A tx SRDO whose record the bound description declares without a writable sub-index 3 is expected at an SRVT of 20 ms, and a peer that aborts the upload of a sub-index 3 the description does not declare with 0609 0011h does not implement it, which is no difference (CiA 319 §6.2). 13FFh:00, the checksums of the SRDOs expected and 13FEh pass the peer-SDO gate before the first frame. The identity of CiA 319 §5.2 is not read: it belongs to the configuration, and a DCF bound for the boot-up is bound for that node-id. Nothing is written. The peer's SDO channel is reserved for the whole transaction: it waits for a call to that peer already in flight, and a concurrent SDO call of this node to that peer is refused as already in flight. The transaction works from the description and the expectation as they were when it started — when it owns the peer's channel (the gate of every transfer and the comparison use copies taken then): a rebind, an unbind or an edit in place of the bound description, or a change to expected, after that takes effect for the next call.

System.Threading.Tasks.Task<CanKit.Pro.CANopen.Safety.PeerSafetyResult> VerifyPeerSafetyConfigurationAsync(byte peerNodeId, CanKit.Pro.CANopen.Safety.PeerSafetyConfiguration expected, System.Threading.CancellationToken cancellationToken=default(System.Threading.CancellationToken));

Parameters

peerNodeId Byte

expected PeerSafetyConfiguration

cancellationToken CancellationToken

Returns

Task<PeerSafetyResult>

Exceptions

InvalidOperationException
The peer's 13FFh:00 is not exactly one byte (it is UNSIGNED8; none, two or four bytes are refused, a longer one is not cut to its low byte), or the count is above 64 (§8.4.2.2) or above the bound description's highest SRDO record (the gate implies no record above it, so the SRDOs the peer has beyond the file could not be verified) — refused before any further frame.

PeerSdoAccessException
The bound description does not declare 13FFh:00, 13FFh:n of an SRDO expected, or 13FEh — refused before the first frame; or, once the count is read, sub-index 01h of a record up to it — refused before any further frame.

ArgumentException
The expectation names an SRDO above the peer's count, or gives a tx SRDO whose record the description declares without a writable sub-index 3 an SRVT other than 20 ms (CiA 319 §6.2); the parameter named is expected.

Events

ICanOpenSafety.GlobalFailsafeCommandReceived Event

A GFC arrived while Operational, whatever 1300h held; the node set it to 1 (including the node's own, on a bus that echoes).

event EventHandler<GlobalFailsafeCommandReceivedEventArgs>? GlobalFailsafeCommandReceived;

Event Type

EventHandler<GlobalFailsafeCommandReceivedEventArgs>

ICanOpenSafety.SrdoReceived Event

A consumer SRDO received a valid pair and wrote it to the mapped objects.

event EventHandler<SrdoReceivedEventArgs>? SrdoReceived;

Event Type

EventHandler<SrdoReceivedEventArgs>

ICanOpenSafety.SrdoStateChanged Event

An SRDO became valid or invalid (transitions only; never dropped).

event EventHandler<SrdoStateChangedEventArgs>? SrdoStateChanged;

Event Type

EventHandler<SrdoStateChangedEventArgs>