Understanding CANopen SDO Abort Codes
Anyone commissioning CANopen devices knows the situation: an SDO access to an object fails and the tool reports a 32-bit value such as 0x06090011 or 0x08000022. Without looking it up, that number says very little — yet it carries the decisive information about why the access was rejected. This article explains how abort codes are structured and shows, for the cases that actually turn up in the field, what really lies behind them.
What is an SDO abort?
The SDO service (Service Data Object) transfers configuration and diagnostic data between an SDO client (usually a CANopen manager (master) or a tool) and an SDO server (the addressed device). If an ongoing transfer cannot be completed normally, the other side terminates it with an Abort SDO Transfer.
The abort message is always 8 bytes long and structured as follows:
| Byte | Content |
|---|---|
| 0 | Command specifier 0x80 |
| 1–2 | Index of the affected object (LSB first) |
| 3 | Sub-index |
| 4–7 | Abort code, 32 bit, LSB first |
Important for trace analysis: the abort code appears little endian on the bus. Code 0x06020000 therefore shows up in the frame as 00 00 02 06. Anyone reading traces by hand should keep this reversal in mind — it is one of the most common sources of confusion.
An abort is not acknowledged. It ends the transfer immediately, and it works in both directions: the client can abort as well, for example on its own timeout or when the user cancels a running download.
Structure of the abort code
The 32-bit value is not arbitrary but structured:
| Bits | Meaning | Typical values |
|---|---|---|
| 31–24 | Error class | 0x05 protocol error, 0x06 access error, 0x08 other errors |
| 23–16 | Error code within the class | e.g. 0x04 for access errors |
| 15–0 | Additional code, refines the error | e.g. 0x0011 for “sub-index does not exist” |
Roughly speaking, 0x05… concerns the SDO protocol itself, 0x06… the object dictionary, and 0x08… the application behind it. For everyday work, though, that classification is only a first orientation — what matters is the complete code including the additional code, because only that names the actual cause.
Where to find the complete list
The normative source for all defined abort codes is CiA 301 (“CANopen application layer and communication profile”), in the section on the SDO protocol. There they are tabulated completely and bindingly — including the values you will never encounter in the field. The document is available from CAN in Automation and belongs on every CANopen developer’s machine anyway.
Repeating that list here would help nobody: an abort code should not be looked up in a table in the first place, but displayed by the tool. The more interesting question is a different one — which codes actually occur, and what do they mean beyond their definition?
The codes that actually occur in practice
0x05040000 — SDO timeout
By far the most frequent error during commissioning, and the one least likely to have anything to do with the object dictionary. Typical causes, in the order in which they should be checked:
- Wrong node ID. The client transmits on
0x600 + node IDand waits for0x580 + node ID. If the node number is wrong, nobody answers at all. - Device in NMT state Stopped. In the Stopped state only NMT and error control are active — SDOs are not served. An
Enter Pre-Operationalresolves this instantly. See the article on CANopen network management for details. - Bit rate mismatch or missing termination. If no frame is acknowledged at all, the bus is the problem, not CANopen.
- Client timeout too short. Devices that block while writing to flash or during a store operation need longer than the usual 1000 ms. Some servers do respond correctly, just late.
A look at the trace clarifies this in seconds: is a request visible on the bus at all, and does the node answer with anything?
0x06020000 — object does not exist
The device does not know the index. Almost always one of three causes:
- The EDS file in use does not match the actual firmware version of the device. A perennial issue with manufacturer-specific objects from
0x2000onwards. - The index was entered incorrectly, or the tool interprets the byte order differently than expected.
- An optional object is simply not implemented in this particular device. Many CiA 301 objects are optional —
0x1015(EMCY inhibit time) or0x1003(error history), for instance.
The code is clearly distinct from the sub-index error 0x06090011: with 0x06020000 the entire object is missing, with 0x06090011 it exists but the requested sub-index does not. For arrays it is then worth reading sub-index 0, which reports the actual number of entries.
0x06010002 — attempt to write a read-only object
Besides the obvious case (writing to 0x1018, the identity object), there are two classics:
- Sub-index 0 of arrays and records is defined as
constin many objects and cannot be changed. - Changing a PDO mapping while the PDO is valid. Per CiA 301, bit 31 in the PDO’s COB-ID entry must be set first (PDO invalid), then sub-index 0 of the mapping parameter written to 0, then the mapping changed, then sub-index 0 set to the new count, and finally the PDO made valid again. Skip this sequence and, depending on the stack, you get
0x06010002or0x06040042. More on this in the article on PDO linking.
0x06070010, 0x06070012, 0x06070013 — length errors
The client sent a different data length than the object expects. In practice this is nearly always a tool or client issue rather than a device fault: in an expedited download, the number of valid bytes must be indicated correctly via the n bits in the command specifier. If an UNSIGNED16 is written with four bytes, a standard-compliant server rejects it. Some stacks are tolerant here and silently accept oversized accesses — so a device that aborts correctly is not the worse one.
0x06090030, 0x06090031, 0x06090032 — value out of range
The data type is right, the value is not. The permitted limits are given in the EDS file in the LowLimit and HighLimit entries. If a device aborts here even though the value should be allowed according to the EDS, the EDS file is usually out of date.
0x08000022 — wrong device state
The access would be permissible in principle but is blocked in the current state. Typical situations:
- Configuration parameters that can only be changed in the Pre-operational state.
- CiA 402 drives in which certain parameters are locked in the Operation Enabled state.
- An ongoing store or update operation blocking further accesses.
The difference from 0x08000021 (local control) is subtle: there, local operation — a hand terminal or a selector switch on the device — prevents access via the bus.
0x08000020 — application rejects the data
The generic fallback when an application callback in the device rejects the value without supplying a more specific reason. A common example: writing to 0x1010 (store parameters) without the required signature. The expected value is the ASCII sequence “save” as UNSIGNED32, i.e. 0x65766173; likewise 0x1011 (restore) requires “load”, i.e. 0x64616F6C. Any other value leads to an abort.
0x05030000 — toggle bit not alternated
Relevant only for segmented transfers. Every segment must alternate the toggle bit. The error points to duplicated frames, a retransmission at CAN level, or a faulty client implementation — with commercial stacks on both sides it is practically never seen.
The right tool saves the lookup
Nobody should have to look up abort codes in a table — and translating the raw bytes 80 17 10 00 02 00 01 06 back by hand is a pure waste of time. A tool with CANopen interpretation takes care of both: it recognises the abort message, reverses the byte order, resolves index and sub-index against the EDS file, and displays the abort code in plain text.
Two tools cover the typical use cases:
- emotas CANinterpreter with the CANopen Interpretation plug-in — the way to go when you want to observe what a third-party CANopen manager or a host controller is actually doing on the bus. Instead of raw data bytes, the tool shows the CANopen service, for example a read SDO access to the heartbeat producer object
0x1017— and, in the error case, the decoded abort code. Filtering works both by node ID and by CANopen service, which makes all the difference on busy networks. Together with the recording and replay functions, this is the right choice for sporadic faults that cannot be reproduced on demand. - emotas CANopen DeviceExplorer — the way to go when you trigger the access yourself. The object browser reads the EDS file and presents every object with its data type, access rights and value limits. In many cases that shows you before the access why it is going to fail — because an object is
ro, say, or because the requested sub-index does not exist at all. If an SDO does fail, the abort code is reported directly in plain text. CANopen interpretation is already part of the Basic package, so object access and trace view live in the same tool.
For recurring checks, the scripting plug-in pays off: a script that walks through a list of objects and logs the returned abort codes finds inconsistencies between EDS and firmware in seconds rather than hours.
A workflow for troubleshooting
A pragmatic order that resolves most cases within minutes:
- Record a trace and have it interpreted. Only once request, response and abort are available in plain text do you know whether the device answered at all, and with which code. Skip this step and you are guessing.
- Check the NMT state. Some timeouts disappear after an
Enter Pre-Operational. - Cross-check the EDS against the device. Object actually present, access rights, data type, value limits — a matter of seconds in the object browser.
- Repeat the access in isolation. A single SDO access from the tool, with no CANopen manager running in parallel, separates genuine object errors from state-dependent locks.
- Ask the manufacturer — but with the specific abort code, index and sub-index. That shortens any support request considerably.
For device manufacturers
The abort code is part of the device’s user interface. Returning a blanket 0x08000000 (general error) forces every integrator to guess and generates support effort. Three recommendations:
-
- Use the most specific applicable code, in particular the range errors
0x06090030to0x06090032instead of a generic0x08000020. - Report state-dependent locks consistently with
0x08000022, and state in the device documentation which objects are writable in which state. - Document the abort codes your device uses — just as you would the emergency error codes.
- Use the most specific applicable code, in particular the range errors
