26 #ifndef LELY_NO_CO_EMCY 101 struct timespec inhibit;
115 co_unsigned32_t ef[0xfe];
154 co_emcy_t *emcy, co_unsigned8_t
id, co_unsigned32_t cobid);
170 static int co_emcy_timer(
const struct timespec *tp,
void *data);
183 const co_unsigned8_t msef[5]);
192 __co_emcy_alloc(
void)
194 void *ptr = malloc(
sizeof(
struct __co_emcy));
201 __co_emcy_free(
void *ptr)
221 goto error_sub_1001_00;
236 goto error_create_timer;
262 co_unsigned8_t maxid =
MIN(co_obj_get_val_u8(obj_1028, 0x00),
264 for (co_unsigned8_t
id = 1;
id <= maxid;
id++) {
265 co_unsigned32_t cobid =
266 co_obj_get_val_u32(obj_1028,
id);
326 trace(
"creating EMCY producer service");
333 goto error_alloc_emcy;
336 if (!__co_emcy_init(emcy, net, dev)) {
338 goto error_init_emcy;
344 __co_emcy_free(emcy);
354 trace(
"destroying EMCY producer service");
355 __co_emcy_fini(emcy);
356 __co_emcy_free(emcy);
378 const co_unsigned8_t msef[5])
390 diag(
DIAG_INFO, 0,
"EMCY: %04X %02X %u %u %u %u %u", eec, er,
391 msef[0], msef[1], msef[2], msef[3], msef[4]);
444 co_unsigned8_t msef[5] = { 0 };
508 trace(
"creating EMCY consumer service for node %d",
id);
515 goto error_alloc_node;
524 goto error_create_recv;
541 trace(
"destroying EMCY consumer service for node %d", node->
id);
560 #ifndef LELY_NO_CANFD 562 if (msg->
flags & CAN_FLAG_EDL)
567 co_unsigned16_t
eec = 0;
570 co_unsigned8_t
er = msg->
len >= 3 ? msg->
data[2] : 0;
571 co_unsigned8_t msef[5] = { 0 };
573 memcpy(msef, msg->
data + 3,
574 MAX((uint_least8_t)(msg->
len - 3), 5));
577 trace(
"EMCY: received %04X %02X", eec, er);
579 emcy->
ind(emcy, node->
id, eec, er, msef, emcy->
data);
596 val_1003->
n =
MIN((co_unsigned8_t)emcy->
nmsg, nsubidx - 1);
597 for (
int i = 0; i < val_1003->
n; i++)
599 for (
int i = val_1003->
n; i < nsubidx - 1; i++)
605 static co_unsigned32_t
614 co_unsigned32_t ac = 0;
646 static co_unsigned32_t
654 co_unsigned32_t ac = 0;
667 co_unsigned32_t cobid = val.u32;
668 co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
669 if (cobid == cobid_old)
677 if (valid && valid_old && canid != canid_old) {
707 emcy->
nodes[
id - 1] = node;
710 uint_least32_t
id = cobid;
711 uint_least8_t flags = 0;
721 emcy->
nodes[
id - 1] = NULL;
727 static co_unsigned32_t
736 co_unsigned32_t ac = 0;
756 co_unsigned32_t cobid = val.u32;
757 co_unsigned32_t cobid_old = co_sub_get_val_u32(sub);
758 if (cobid == cobid_old)
766 if (valid && valid_old && canid != canid_old) {
803 const co_unsigned8_t msef[5])
814 co_unsigned32_t cobid = co_obj_get_val_u32(obj_1014, 0x00);
831 memcpy(msg.
data + 3, msef, 5);
849 co_unsigned16_t inhibit = co_dev_get_val_u16(emcy->
dev, 0x1015, 0x00);
851 struct timespec now = { 0, 0 };
870 #endif // !LELY_NO_CO_EMCY A CANopen SDO upload/download request.
A CAN or CAN FD format frame.
#define CO_NUM_NODES
The maximum number of nodes in a CANopen network.
void can_buf_fini(struct can_buf *buf)
Finalizes a CAN frame buffer.
#define CO_EMCY_COBID_VALID
The bit in the EMCY COB-ID specifying whether the EMCY exists and is valid.
size_t can_buf_size(const struct can_buf *buf)
Returns the number of frames available for reading in a CAN buffer.
static co_unsigned32_t co_1014_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1014 (COB-ID emergency messa...
static co_unsigned32_t co_1003_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1003 (Pre-defined error fiel...
void co_obj_set_dn_ind(co_obj_t *obj, co_sub_dn_ind_t *ind, void *data)
Sets the download indication function for a CANopen object.
uint_least32_t id
The identifier (11 or 29 bits, depending on the CAN_FLAG_IDE flag).
uint_least8_t len
The number of bytes in data (or the requested number of bytes in case of a remote frame)...
co_emcy_t * emcy
A pointer to the EMCY service.
static void co_emcy_flush(co_emcy_t *emcy)
Sends any messages in the CAN frame buffer unless the inhibit time has not yet elapsed, in which case it sets the CAN timer.
uint_least16_t ldle_u16(const uint_least8_t src[2])
Loads a 16-bit unsigned integer in little-endian byte order.
int errnum2c(errnum_t errnum)
Transforms a platform-independent error number to a native error code.
void set_errnum(errnum_t errnum)
Sets the current (thread-specific) platform-independent error number to errnum.
void diag(enum diag_severity severity, int errc, const char *format,...)
Emits a diagnostic message.
void stle_u16(uint_least8_t dst[2], uint_least16_t x)
Stores a 16-bit unsigned integer in little-endian byte order.
#define CO_SDO_AC_PARAM_VAL
SDO abort code: Invalid value for parameter (download only).
A union of the CANopen static data types.
void can_net_get_time(const can_net_t *net, struct timespec *tp)
Retrieves the current time of a CAN network interface.
can_timer_t * timer
A pointer to the CAN timer.
#define CO_SDO_AC_ERROR
SDO abort code: General error.
static int co_emcy_node_recv(const struct can_msg *msg, void *data)
The CAN receive callback function for a remote CANopen EMCY producer node.
static int co_emcy_set_1003(co_emcy_t *emcy)
Sets the value of CANopen object 1003 (Pre-defined error field).
#define MIN(a, b)
Returns the minimum of a and b.
void can_timer_start(can_timer_t *timer, can_net_t *net, const struct timespec *start, const struct timespec *interval)
Starts a CAN timer and registers it with a network interface.
int can_buf_init(struct can_buf *buf, size_t size)
Initializes a CAN frame buffer.
#define CAN_MASK_BID
The mask used to extract the 11-bit Base Identifier from a CAN frame.
This header file is part of the CANopen library; it contains the Service Data Object (SDO) declaratio...
co_unsigned8_t er
The error register.
struct co_emcy_node * nodes[CO_NUM_NODES]
An array of pointers to remote nodes.
This header file is part of the CANopen library; it contains the CANopen value declarations.
void set_errc(int errc)
Sets the current (thread-specific) native error code to errc.
struct timespec inhibit
The time at which the next EMCY message may be sent.
void can_timer_set_func(can_timer_t *timer, can_timer_func_t *func, void *data)
Sets the callback function invoked when a CAN timer is triggered.
void co_emcy_peek(const co_emcy_t *emcy, co_unsigned16_t *peec, co_unsigned8_t *per)
Retrieves, but does not pop, the most recent CANopen EMCY message from the stack. ...
can_recv_t * can_recv_create(void)
Creates a new CAN frame receiver.
#define CO_DEFTYPE_UNSIGNED32
The data type (and object index) of a 32-bit unsigned integer.
void timespec_add_usec(struct timespec *tp, uint_least64_t usec)
Adds usec microseconds to the time at tp.
uint_least8_t data[CAN_MSG_MAX_LEN]
The frame payload (in case of a data frame).
void co_emcy_set_ind(co_emcy_t *emcy, co_emcy_ind_t *ind, void *data)
Sets the indication function invoked when a CANopen EMCY message is received.
static void co_emcy_node_destroy(struct co_emcy_node *node)
Destroys a remote CANopen EMCY producer node.
co_unsigned8_t n
Number of errors.
This header file is part of the utilities library; it contains the time function declarations.
This header file is part of the CANopen library; it contains the emergency (EMCY) object declarations...
co_emcy_ind_t * ind
A pointer to the indication function.
co_unsigned16_t eec
The emergency error code.
void co_emcy_ind_t(co_emcy_t *emcy, co_unsigned8_t id, co_unsigned16_t eec, co_unsigned8_t er, co_unsigned8_t msef[5], void *data)
The type of a CANopen EMCY indication function, invoked when an EMCY message is received.
void can_recv_destroy(can_recv_t *recv)
Destroys a CAN frame receiver.
void * data
A pointer to user-specified data for ind.
This header file is part of the utilities library; it contains the byte order (endianness) function d...
The Remote Transmission Request (RTR) flag (unavailable in CAN FD format frames). ...
This is the internal header file of the CANopen library.
size_t can_buf_reserve(struct can_buf *buf, size_t n)
Resizes a CAN frame buffer, if necessary, to make room for at least n additional frames.
This header file is part of the CAN library; it contains the CAN frame buffer declarations.
co_emcy_t * co_emcy_create(can_net_t *net, co_dev_t *dev)
Creates a new CANopen EMCY producer/consumer service.
#define CAN_MAX_LEN
The maximum number of bytes in the payload of a CAN format frame.
void co_emcy_destroy(co_emcy_t *emcy)
Destroys a CANopen EMCY producer/consumer service.
int get_errc(void)
Returns the last (thread-specific) native error code set by a system call or library function...
#define MAX(a, b)
Returns the maximum of a and b.
void can_timer_destroy(can_timer_t *timer)
Destroys a CAN timer.
int co_sub_dn(co_sub_t *sub, void *val)
Downloads (moves) a value into a CANopen sub-object if the refuse-write-on-download flag (CO_OBJ_FLAG...
#define CO_DEFTYPE_UNSIGNED8
The data type (and object index) of an 8-bit unsigned integer.
can_recv_t * recv
A pointer to the CAN frame receiver.
#define CO_EMCY_COBID_FRAME
The bit in the EMCY COB-ID specifying whether to use an 11-bit (0) or 29-bit (1) CAN-ID.
size_t nmsg
The number of messages in msgs.
co_unsigned8_t co_obj_get_subidx(const co_obj_t *obj, co_unsigned8_t maxsubidx, co_unsigned8_t *subidx)
Retrieves a list of sub-indices in a CANopen object.
int errno2c(int errnum)
Transforms a standard C error number to a native error code.
This header file is part of the utilities library; it contains the diagnostic declarations.
#define CO_SDO_AC_NO_WRITE
SDO abort code: Attempt to write a read only object.
void stle_u32(uint_least8_t dst[4], uint_least32_t x)
Stores a 32-bit unsigned integer in little-endian byte order.
void co_emcy_get_ind(const co_emcy_t *emcy, co_emcy_ind_t **pind, void **pdata)
Retrieves the indication function invoked when a CANopen EMCY message is received.
int timespec_cmp(const void *p1, const void *p2)
Compares two times.
size_t can_buf_read(struct can_buf *buf, struct can_msg *ptr, size_t n)
Reads, and removes, frames from a CAN frame buffer.
void can_recv_set_func(can_recv_t *recv, can_recv_func_t *func, void *data)
Sets the callback function used to process CAN frames with a receiver.
uint_least8_t flags
The flags (any combination of CAN_FLAG_IDE, CAN_FLAG_RTR, CAN_FLAG_FDF, CAN_FLAG_BRS and CAN_FLAG_ESI...
co_obj_t * co_sub_get_obj(const co_sub_t *sub)
Returns the a pointer to the CANopen object containing the specified sub-object.
The Identifier Extension (IDE) flag.
can_timer_t * can_timer_create(void)
Creates a new CAN timer.
A remote CANopen EMCY producer node.
co_sub_t * co_dev_find_sub(const co_dev_t *dev, co_unsigned16_t idx, co_unsigned8_t subidx)
Finds a sub-object in the object dictionary of a CANopen device.
struct co_emcy_msg * msgs
An array of EMCY messages. The first element is the most recent.
void co_val_fini(co_unsigned16_t type, void *val)
Finalizes a value of the specified data type.
int can_net_send(can_net_t *net, const struct can_msg *msg)
Sends a CAN frame from a network interface.
static int co_emcy_send(co_emcy_t *emcy, co_unsigned16_t eec, co_unsigned8_t er, const co_unsigned8_t msef[5])
Adds an EMCY message to the CAN frame buffer and sends it if possible.
co_unsigned8_t id
The node-ID.
#define CO_SDO_AC_NO_SUB
SDO abort code: Sub-index does not exist.
size_t can_buf_write(struct can_buf *buf, const struct can_msg *ptr, size_t n)
Writes frames to a CAN frame buffer.
int co_sdo_req_dn_val(struct co_sdo_req *req, co_unsigned16_t type, void *val, co_unsigned32_t *pac)
Copies the next segment of the specified CANopen SDO download request to the internal buffer and...
struct can_buf buf
The CAN frame buffer.
A CANopen EMCY producer/consumer service.
int co_emcy_clear(co_emcy_t *emcy)
Clears the CANopen EMCY message stack and broadcasts the 'error reset/no error' message if the EMCY p...
This header file is part of the CANopen library; it contains the device description declarations...
static co_unsigned32_t co_1028_dn_ind(co_sub_t *sub, struct co_sdo_req *req, void *data)
The download indication function for (all sub-objects of) CANopen object 1028 (Emergency consumer obj...
co_unsigned8_t co_sub_get_subidx(const co_sub_t *sub)
Returns the sub-index of a CANopen sub-object.
This header file is part of the C11 and POSIX compatibility library; it includes <stdlib.h> and defines any missing functionality.
int co_emcy_push(co_emcy_t *emcy, co_unsigned16_t eec, co_unsigned8_t er, const co_unsigned8_t msef[5])
Pushes a CANopen EMCY message to the stack and broadcasts it if the EMCY producer service is active...
co_unsigned16_t co_sub_get_type(const co_sub_t *sub)
Returns the data type of a CANopen sub-object.
can_net_t * net
A pointer to a CAN network interface.
can_net_t * co_emcy_get_net(const co_emcy_t *emcy)
Returns a pointer to the CAN network of an EMCY producer/consumer service.
co_sub_t * sub_1001_00
A pointer to the error register object.
static struct co_emcy_node * co_emcy_node_create(co_emcy_t *emcy, co_unsigned8_t id)
Creates a new remote CANopen EMCY producer node.
co_unsigned16_t co_obj_get_idx(const co_obj_t *obj)
Returns the index of a CANopen object.
This header file is part of the CANopen library; it contains the object dictionary declarations...
#define CAN_MSG_INIT
The static initializer for can_msg.
co_obj_t * obj_1003
A pointer to the pre-defined error field object.
void can_recv_start(can_recv_t *recv, can_net_t *net, uint_least32_t id, uint_least8_t flags)
Registers a CAN frame receiver with a network interface and starts processing frames.
co_obj_t * co_dev_find_obj(const co_dev_t *dev, co_unsigned16_t idx)
Finds an object in the object dictionary of a CANopen device.
co_unsigned32_t ef[0xfe]
An array of standard error fields.
static int co_emcy_set_1028(co_emcy_t *emcy, co_unsigned8_t id, co_unsigned32_t cobid)
Sets the value of CANopen object 1028 (Emergency consumer object).
co_dev_t * dev
A pointer to a CANopen device.
void * co_obj_addressof_val(const co_obj_t *obj)
Returns the address of the value of a CANopen object.
int co_emcy_pop(co_emcy_t *emcy, co_unsigned16_t *peec, co_unsigned8_t *per)
Pops the most recent CANopen EMCY message from the stack and broadcasts an 'error reset' message if t...
static int co_emcy_timer(const struct timespec *tp, void *data)
The CAN timer callback function for an EMCY service.
#define CAN_MASK_EID
The mask used to extract the 29-bit Extended Identifier from a CAN frame.
The pre-defined error field.
co_dev_t * co_emcy_get_dev(const co_emcy_t *emcy)
Returns a pointer to the CANopen device of an EMCY producer/consumer service.
An informational message.