EtherCAT Slave Library

EtherCAT is a real-time open communication protocol based on Ethernet networks. The standardization process is coordinated by the EtherCAT Technology Group.

This library (lib_ethercat ) allows an abstract access to the application layer of the EtherCAT communication stack. The underlying device access and data transfer is handled without the interaction of the device user application.

The EtherCAT access is implemented using a single thread. All communication is done by interfaces. The PDOs are stored transparently for quick access.

The library supports the following protocols:

  • PDO transfer
  • CAN over EtherCAT (CoE) with CiA402
  • File over EtherCAT (FoE)

How to Use

First you have to decide which build of the library to use. The available builds and theire respective usage are:

libethercat_service:
 This is the default library for most use cases. Add this library if you want to deploy your application onto a node with a bootloader installed.
libethercat_service_standalone:
 The standalone library is meant to be used during development (when you start your application with the run command in xTIMEComposer). This library allows applications which are directly flashed to the device without bootloader.
libethercat_service_debug and libethercat_service_hwtest:
 Are libraries for debugging purposes.
libethercat_service_boot:
 This build is specific for the EtherCAT enabled bootloader. It supports a subset of the EtherCAT features.

To choose the correct library you have to change the MODULE_LIBRARIES entry in you application Makefile. For example to use the standalone library during development with the Debug build and the standard one for the flashable Release build you can add

ifeq ($(CONFIG),Debug)
        MODULE_LIBRARIES = ethercat_service_standalone
else
        MODULE_LIBRARIES = ethercat_service
endif

to your Makefile.

Independent of the flavour of the library you need to include the main header ethercat_service.h into you application. This header file provides the interface communication interfaces and the main service function.

ethercat_service():
 start the EtherCAT communication and serve the data via interfaces

After the call to ethercat_service() the library is operational. And the master is able to communicate with the device via EtherCAT.

If the firmware also want to use the device object dictionary than the module canopen_interface_service needs to be added to the application. With the interface i_co_communication the EtherCAT service is able to access the object dictionary and the PDO storage.

The interface i_foe_communicaiton provides the necessary communication interface for file transferes. The main user of this is the file_service.

The optional EoE protocol is currently not available, so please set the i_eoe_commmunication parameter in ethercat_service() call to null.

CANopen communication

The CANopen communication is split up in the process data communication (PDO exchange) for real time process data and the asynchronous SDO requests over the CoE mailbox communication. The later one is used to request non-real-time data for device configuration parameters and special functionalities of the device.

The EtherCAT service will write to the SOMANET CANopen Interface <module_canopen_interface> if new values are available or a new request is scheduled.

For more information see the help of SOMANET CANopen Interface <module_canopen_interface> for more information.

FoE Communication

The FoE communication is used to upload a new update firmware (in bootstage mode) or for general filetransfer. For general file transfer the firmware needs to support the SPIFFS and file services (see spiffs_service and file_service for more information).

If a FoE request arrives at the device the notification data_ready() is raised. The client application is then required to get the notification type with the interface call get_notification_type(). There are two possible types of notification FOE_NOTIFY_DATA for incoming data and FOE_NOTIFY_DATA_REQUEST if the master requests a file.

In any case the client application can get the filename with the interface call requested_filename(filename), so the application knows which file is currently to be transfered.

In case of a FOE_NOTIFY_DATA notification the client application needs to request the recently arrived packet with read_data() and mark the transfer as processed with the result() interface call to be able to receive the next packet. A incomplete packet indicates the last packet.

To handle a FOE_NOTIFY_DATA_REQUEST the client needs to write a data chunk with the interfcae call write_data(). If the next packet can be written is announced with the data_ready() notification.

API

The main user API for the lib_ethercat component is found in ethercat_service.h.

interface i_co_communication

Communication class for OD service request to network service.

void pdo_in(uint8_t pdo_number, unsigned int size, pdo_size_t data_in[])

Receives PDOs from master to slave.

Parameters:
  • pdo_number – PDO number
  • size – PDO buffer size
  • data_in – PDO buffer
unsigned int pdo_out(uint8_t pdo_number, pdo_size_t data_out[])

Transfers PDOs from slave to master.

Parameters:
  • pdo_number – PDO number
  • data_in – PDO buffer
Returns:

PDO buffer size

{uint32_t, uint32_t, uint8_t} o od_get_object_value(uint16_t index_, uint8_t subindex)

Returns an object value from dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Object value, bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

uint8_t od_set_object_value(uint16_t index_, uint8_t subindex, uint32_t value)

Set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value, which will set in OD
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found

{uint32_t, uint8_t} o od_master_get_object_value(uint16_t index_, uint8_t subindex, size_t capacity, uint8_t value_out[])

Master reads an object value from dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • capacity – The capacity of the output array value_out
  • value_out – The value as byte array of the requested entry
Returns:

bitlength Read bitlength of the entry value - Object value, bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

Returns:

error_out 0 on no error

uint8_t od_master_set_object_value(uint16_t index_, uint8_t subindex, uint8_t value[], size_t capacity)

Master set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value array, which will set in OD
  • capacity – Size of the value field
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

uint8_t od_slave_set_object_value(uint16_t index_, uint8_t subindex, uint8_t value[], size_t capacity)

Slave set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value array, which will set in OD
  • capacity – Size of the value field
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

{ uint32_t, uint8_t } o od_slave_get_object_value(uint16_t index_, uint8_t subindex, size_t capacity, uint8_t value[])

Slave set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • capacity – Size of the value field
  • value – Value array, which will hold the objects entry value
Returns:

bitlength Number of bytes written into value buffer

Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

{uint32_t, uint8_t} o od_get_object_value_buffer(uint16_t index_, uint8_t subindex, uint8_t data_buffer[])

Returns an object value from dictionary.

NOTE: For CAN the data_buffer is maxiumum 8 byte wide.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • data_buffer – OD value
Returns:

Bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

uint8_t od_set_object_value_buffer(uint16_t index_, uint8_t subindex, uint8_t data_buffer[])

Set an object value in dictionary.

NOTE: For CAN the data_buffer is maxiumum 8 byte wide.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • data_buffer – Value, which will set in OD
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found

size_t od_changed_values_count(void)

Check how many entry values changed.

The number of changed entry values is incremented everytime the master updates a value and decremented when the application reads a value from this dictioanry.

Returns:Number of changed entry values
int od_entry_has_changed(uint16_t index, uint8_t subindex)

Check specific object if it changed.

Parameters:
  • index – Index of the object entry to test
  • subindex – Subindex of the object entry to test
Returns:

0 entry did not changed, 1 entry value is modified

{uint16_t, uint8_t} o od_get_next_changed_element(void)

Find the next changed object entry.

The last read object entry value is stored internally, this request returns the next higher index/subindex which has not been read until now.

Returns:index and subindex of the next changed element, if index == subindex == 0 then no changed element is present.
{struct _sdoinfo_entry_description, uint8_t} o od_get_entry_description(uint16_t index_, uint8_t subindex)

Get whole entry description of object.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • valueinfo – put these additional values in the reply, possible bits to set are: 0x04 Unit, 0x08 default value, 0x10 minimum value, 0x20 maximum value not all values are available for all entries.
Returns:

entry description, error

size_t od_get_entry_description_value(uint16_t index_, uint8_t subindex, uint8_t valuetype, size_t capacity, uint8_t values[])

Get specific values for SDO Information entry request.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • valueinfo – put these additional values in the reply, possible bits to set are: 0x04 Unit, 0x08 default value, 0x10 minimum value, 0x20 maximum value not all values are available for all entries.
Returns:

size of the value or 0 if unavailable

void od_get_all_list_length(uint16_t lists[])

Returns an array with five length entrys (Currently just one entry).

The list lengths are: Arrary Index | List type ———-+——– 0 | All objects (without subindex) 1 | RxPDO Mappable 2 | TxPDO Mappable 3 | List Replace 4 | List all Startup Parameters

Parameters:
  • Array – with all list lengths
int od_get_list(uint16_t list[], unsigned size, unsigned listtype)

Returns a list with all index.

Parameters:
  • list – array of indexes for
  • size – capacity of the list
  • listtype – type of indexes to return in the list (values: 1 - all, 2 - RX mappable, 3 - TX mappable, 4 - backup, 5 - startup)
Returns:

List length

int od_get_object_description(struct _sdoinfo_entry_description &obj, uint16_t index_, uint8_t subindex)

Get single entry description.

Parameters:
  • obj – SDO info struct
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

0 if found else 1

{uint32_t, uint8_t} o od_get_data_length(uint16_t index_, uint8_t subindex)

Get data length of an single OD entry value.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Bitlength, Error

{enum eAccessRights, uint8_t} o od_get_access(uint16_t index_, uint8_t subindex)

Get access type of an single OD entry value.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Access type, Error

void operational_state_change(int opmode)

Set flag “configuration done”.

Parameters:
  • opmode – 1 - if opmode is entered, 0 - if opmode is left.
int in_operational_state(void)

Check if the EtherCAT State Machine (ESM) is in operation mode.

Returns:1 - if drive is in operational state; 0 - otherwise
void configuration_done(void)

Delete flag “configuration done”.

int configuration_get(void)

Get flag status.

Returns:Flag status.
void inactive_communication(void)
enum eSdoCommand command_ready(void)

Get currently requested command.

If this application supports command via object dictionary this method needs to be read regularly to get notified aobut a command request from the master.

Returns:command to process
void command_set_result(int result)

Set result of the last command.

If a command is processed accordingly set the result here. You can use the definitions in

Parameters:
  • result – 0 on success, != 0 on error
int get_brake_request(void)

Check if the master overrieds the break status and tries to engage/disengage the break.

return -1, 0 := do nothing; 1 := engage break; 2 := disengage break;

void pdo_in(uint8_t pdo_number, unsigned int size, pdo_size_t data_in[])

Receives PDOs from master to slave.

Parameters:
  • pdo_number – PDO number
  • size – PDO buffer size
  • data_in – PDO buffer
unsigned int pdo_out(uint8_t pdo_number, pdo_size_t data_out[])

Transfers PDOs from slave to master.

Parameters:
  • pdo_number – PDO number
  • data_in – PDO buffer
Returns:

PDO buffer size

{uint32_t, uint32_t, uint8_t} o od_get_object_value(uint16_t index_, uint8_t subindex)

Returns an object value from dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Object value, bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

uint8_t od_set_object_value(uint16_t index_, uint8_t subindex, uint32_t value)

Set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value, which will set in OD
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found

{uint32_t, uint8_t} o od_master_get_object_value(uint16_t index_, uint8_t subindex, size_t capacity, uint8_t value_out[])

Master reads an object value from dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • capacity – The capacity of the output array value_out
  • value_out – The value as byte array of the requested entry
Returns:

bitlength Read bitlength of the entry value - Object value, bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

Returns:

error_out 0 on no error

uint8_t od_master_set_object_value(uint16_t index_, uint8_t subindex, uint8_t value[], size_t capacity)

Master set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value array, which will set in OD
  • capacity – Size of the value field
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

uint8_t od_slave_set_object_value(uint16_t index_, uint8_t subindex, uint8_t value[], size_t capacity)

Slave set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • value – Value array, which will set in OD
  • capacity – Size of the value field
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

{ uint32_t, uint8_t } o od_slave_get_object_value(uint16_t index_, uint8_t subindex, size_t capacity, uint8_t value[])

Slave set an object value in dictionary.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • capacity – Size of the value field
  • value – Value array, which will hold the objects entry value
Returns:

bitlength Number of bytes written into value buffer

Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found, 7 -> insufficient memory, 255 -> wrong capacity for entry

{uint32_t, uint8_t} o od_get_object_value_buffer(uint16_t index_, uint8_t subindex, uint8_t data_buffer[])

Returns an object value from dictionary.

NOTE: For CAN the data_buffer is maxiumum 8 byte wide.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • data_buffer – OD value
Returns:

Bitlength, Error: 0 -> No error, 2 -> Index not found, 3 -> Subindex not found

uint8_t od_set_object_value_buffer(uint16_t index_, uint8_t subindex, uint8_t data_buffer[])

Set an object value in dictionary.

NOTE: For CAN the data_buffer is maxiumum 8 byte wide.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • data_buffer – Value, which will set in OD
Returns:

Error: 0 -> No error, 1 -> RO, 2 -> Index not found, 3 -> Subindex not found

size_t od_changed_values_count(void)

Check how many entry values changed.

The number of changed entry values is incremented everytime the master updates a value and decremented when the application reads a value from this dictioanry.

Returns:Number of changed entry values
int od_entry_has_changed(uint16_t index, uint8_t subindex)

Check specific object if it changed.

Parameters:
  • index – Index of the object entry to test
  • subindex – Subindex of the object entry to test
Returns:

0 entry did not changed, 1 entry value is modified

{uint16_t, uint8_t} o od_get_next_changed_element(void)

Find the next changed object entry.

The last read object entry value is stored internally, this request returns the next higher index/subindex which has not been read until now.

Returns:index and subindex of the next changed element, if index == subindex == 0 then no changed element is present.
{struct _sdoinfo_entry_description, uint8_t} o od_get_entry_description(uint16_t index_, uint8_t subindex)

Get whole entry description of object.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • valueinfo – put these additional values in the reply, possible bits to set are: 0x04 Unit, 0x08 default value, 0x10 minimum value, 0x20 maximum value not all values are available for all entries.
Returns:

entry description, error

size_t od_get_entry_description_value(uint16_t index_, uint8_t subindex, uint8_t valuetype, size_t capacity, uint8_t values[])

Get specific values for SDO Information entry request.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
  • valueinfo – put these additional values in the reply, possible bits to set are: 0x04 Unit, 0x08 default value, 0x10 minimum value, 0x20 maximum value not all values are available for all entries.
Returns:

size of the value or 0 if unavailable

void od_get_all_list_length(uint16_t lists[])

Returns an array with five length entrys (Currently just one entry).

The list lengths are: Arrary Index | List type ———-+——– 0 | All objects (without subindex) 1 | RxPDO Mappable 2 | TxPDO Mappable 3 | List Replace 4 | List all Startup Parameters

Parameters:
  • Array – with all list lengths
int od_get_list(uint16_t list[], unsigned size, unsigned listtype)

Returns a list with all index.

Parameters:
  • list – array of indexes for
  • size – capacity of the list
  • listtype – type of indexes to return in the list (values: 1 - all, 2 - RX mappable, 3 - TX mappable, 4 - backup, 5 - startup)
Returns:

List length

int od_get_object_description(struct _sdoinfo_entry_description &obj, uint16_t index_, uint8_t subindex)

Get single entry description.

Parameters:
  • obj – SDO info struct
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

0 if found else 1

{uint32_t, uint8_t} o od_get_data_length(uint16_t index_, uint8_t subindex)

Get data length of an single OD entry value.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Bitlength, Error

{enum eAccessRights, uint8_t} o od_get_access(uint16_t index_, uint8_t subindex)

Get access type of an single OD entry value.

Parameters:
  • index – Object dictionary index
  • subindex – Object dictionary subindex
Returns:

Access type, Error

void operational_state_change(int opmode)

Set flag “configuration done”.

Parameters:
  • opmode – 1 - if opmode is entered, 0 - if opmode is left.
int in_operational_state(void)

Check if the EtherCAT State Machine (ESM) is in operation mode.

Returns:1 - if drive is in operational state; 0 - otherwise
void configuration_done(void)

Delete flag “configuration done”.

int configuration_get(void)

Get flag status.

Returns:Flag status.
void inactive_communication(void)
enum eSdoCommand command_ready(void)

Get currently requested command.

If this application supports command via object dictionary this method needs to be read regularly to get notified aobut a command request from the master.

Returns:command to process
void command_set_result(int result)

Set result of the last command.

If a command is processed accordingly set the result here. You can use the definitions in

Parameters:
  • result – 0 on success, != 0 on error
int get_brake_request(void)

Check if the master overrieds the break status and tries to engage/disengage the break.

return -1, 0 := do nothing; 1 := engage break; 2 := disengage break;

interface i_foe_communication

Communication class for FoE communication.

Interface calls: read_data() - access data of the current FoE transfere (max size = 512 as defined by the FoE spec) result() - the consumer sets the FoE result, 0 for success != for Error data_ready() - this signals the consumer that a new data chunk is ready for reading

[[guarded]] enum eFoeStat read_data(int8_t data[])
[[guarded]] void result(uint32_t packet_number, enum eFoeError error)

Result of the recently received packet.

Parameters:
  • packet_number – The packet_number of the recently processed packet.
  • error – For valid error values
[[guarded]] void requested_filename(uint8_t foename[])

Get the requested filename to write to the master.

Parameters:
  • foename – filename of the request (max FOE_MAX_FILENAME_SIZE long)
eFoeStat

Status of FoE request command.

Enum Values:

FOE_STAT_DATA

expecting more data

FOE_STAT_ERROR

a error occured in FoE transfer

FOE_STAT_EOF

end of file reached (no error)

eFoeNotificationType

Notification from the FoE state machine.

Each time

Enum Values:

FOE_NTYPE_UNDEF

The notification could not be associated.

FOE_NTYPE_BOOT

The system should reboot.

FOE_NTYPE_DATA

Incomming data available.

FOE_NTYPE_DATA_REQUEST

Master requested data.

FOE_NTYPE_RESTART

Restart into application (only in bootloader)

eFoeError

Error codes from application.

Enum Values:

FOE_ERROR_NONE

No error.

FOE_ERROR_UNDEFINED

Undefined error.

FOE_ERROR_NOT_FOUND

File was not found or is unavailable.

FOE_ERROR_ACCESS_DENIED

File exists but could not be accessed.

FOE_ERROR_DISK_FULL

Disk full, no space left on device.

FOE_ERROR_ALREADY_EXISTS

File already exists.

FOE_ERROR_BOOTSTRAP_ONLY

Transfer only allowed in BOOTSTRAP state.

FOE_ERROR_NOT_BOOTSTRAP

Transfer not allowed in BOOTSTRAP state.

FOE_ERROR_NO_RIGHTS

Insufficient rights to acccess file.

FOE_ERROR_PROGRAM_ERROR

Internal program error.

Types

EthercatPorts

Structure containing resources required for interfing the EtherCAT chip.

This structure contains resources required for interfing the EtherCAT chip. It consists of 8 ports.

Structure Members:

out port p_ecatRST
in port p_ecatIRQ
in port p_ecatBUSY
out port p_ecatWR
out port p_ecatRD
out port p_ecatCS
port p_ecatData
out port p_ecatAddress

Functions

ethercat_service

Main Call to EtherCAT handler function.

This function should run in a separate thread on the XMOS core controlling the I/O pins for EtherCAT communication.

Parameters:
  • i_ecat_reboot – access the reboot service
  • i_co_communication – class for CANopen related communication and process data
  • i_eoe_communication – class for EoE data exchange
  • i_foe_communication – send, receive and signal for FoE
  • ethercat_class – ports for interfacing EtherCAT chip.