1
0
Fork 0
CANopenLinux/CO_error.h

163 lines
4.9 KiB
C

/**
* 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 <https://github.com/CANopenNode/CANopenNode>, 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 <stdint.h>
#include <errno.h>
#include <string.h>
#include <linux/can.h>
#include <net/if.h>
#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 */