/** * CANopenNode Linux socketCAN Error handling. * * @file CO_error.h * @ingroup CO_socketCAN_ERROR * @author Martin Wagner * @copyright 2018 - 2020 Neuberger Gebaeudeautomation GmbH * * * This file is part of , a CANopen Stack. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this * file except in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and limitations under the License. */ #ifndef CO_ERROR_H #define CO_ERROR_H #include #include #include #include #include #if __has_include("CO_error_custom.h") #include "CO_error_custom.h" #else #include "CO_error_msgs.h" #endif #ifdef __cplusplus extern "C" { #endif /** * @defgroup CO_socketCAN_ERROR CAN errors & Log * CANopen Errors and System message log * * @ingroup CO_socketCAN * @{ */ /** * Message logging function. * * Function must be defined by application. It should record log message to some place, for example syslog() call in * Linux or logging functionality in CANopen gateway @ref CO_CANopen_309_3. * * By default system stores messages in /var/log/syslog file. Log can optionally be configured before, for example to * filter out less critical errors than LOG_NOTICE, specify program name, print also process PID and print also to * standard error, set 'user' type of program, use: * @code setlogmask (LOG_UPTO (LOG_NOTICE)); openlog ("exampleprog", LOG_PID | LOG_PERROR, LOG_USER); * @endcode * * @param priority one of LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR, LOG_WARNING, LOG_NOTICE, LOG_INFO, LOG_DEBUG * @param format format string as in printf */ void log_printf(int priority, const char* format, ...); /** * driver interface state * * CAN hardware can be in the followning states: * - error active (OK) * - error passive (Can't generate error flags) * - bus off (no influence on bus) */ typedef enum { CO_INTERFACE_ACTIVE, /**< CAN error passive/active */ CO_INTERFACE_LISTEN_ONLY, /**< CAN error passive/active, but currently no other device on bus */ CO_INTERFACE_BUS_OFF /**< CAN bus off */ } CO_CANinterfaceState_t; /** * This is how many NO-ACKs need to be received in a row to assume that no other nodes are connected to a bus and * therefore are assuming listen-only */ #define CO_CANerror_NOACK_MAX 16 /** * This is how long we are going to block transmission if listen-only mode is active * * Time is in seconds. */ #define CO_CANerror_LISTEN_ONLY 10 /** * socketCAN interface error handling */ typedef struct { int fd; /**< interface FD */ char ifName[IFNAMSIZ]; /**< interface name as string */ uint32_t noackCounter; /**< counts no ACK on CAN transmission */ volatile unsigned char listenOnly; /**< set to listen only mode */ struct timespec timestamp; /**< listen only mode started at this time */ uint16_t CANerrorStatus; /**< CAN error status bitfield, see @ref CO_CAN_ERR_status_t */ } CO_CANinterfaceErrorhandler_t; /** * Initialize CAN error handler * * We need one error handler per interface * * @param CANerrorhandler This object will be initialized. * @param fd interface file descriptor * @param ifname interface name as string */ void CO_CANerror_init(CO_CANinterfaceErrorhandler_t* CANerrorhandler, int fd, const char* ifname); /** * Reset CAN error handler * * @param CANerrorhandler CAN error object. */ void CO_CANerror_disable(CO_CANinterfaceErrorhandler_t* CANerrorhandler); /** * Message received event * * When a message is received at least one other CAN module is connected. Function clears listenOnly and noackCounter * error flags. * * @param CANerrorhandler CAN error object. */ void CO_CANerror_rxMsg(CO_CANinterfaceErrorhandler_t* CANerrorhandler); /** * Check if interface is ready for message transmission * * Message mustn't be transmitted if not ready. * * @param CANerrorhandler CAN error object. * @return CO_INTERFACE_ACTIVE message transmission ready */ CO_CANinterfaceState_t CO_CANerror_txMsg(CO_CANinterfaceErrorhandler_t* CANerrorhandler); /** * Error message received event * * This handles all received error messages. * * @param CANerrorhandler CAN error object. * @param msg received error message * @return #CO_CANinterfaceState_t */ CO_CANinterfaceState_t CO_CANerror_rxMsgError(CO_CANinterfaceErrorhandler_t* CANerrorhandler, const struct can_frame* msg); /** @} */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CO_ERROR_H */