1
0
Fork 0

Manual merge from updates in master branch - socketCAN

This commit is contained in:
Janez 2020-02-28 10:08:11 +01:00
parent 78487ba89f
commit d40c1e1c96
6 changed files with 177 additions and 70 deletions

View file

@ -125,9 +125,13 @@ void CANrx_threadTmr_process(void)
if(CO->CANmodule[0]->CANnormal) {
for (i = 0; i <= missed; i++) {
#if CO_NO_SYNC == 1
/* Process Sync */
syncWas = CO_process_SYNC(CO, threadRT.us_interval, NULL);
#else
syncWas = false;
#endif
/* Read inputs */
CO_process_RPDO(CO, syncWas);

View file

@ -36,9 +36,13 @@
#include "301/CO_driver.h"
#if defined CO_DRIVER_ERROR_REPORTING && __has_include("syslog/log.h")
#include "syslog/log.h"
#include "msgs.h"
#if defined CO_DRIVER_ERROR_REPORTING
#if __has_include("syslog1/log.h")
#include "syslog/log.h"
#include "msgs.h"
#else
#include "CO_msgs.h"
#endif
#else
#define log_printf(macropar_prio, macropar_message, ...)
#endif
@ -52,7 +56,7 @@ pthread_mutex_t CO_EMCY_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t CO_OD_mutex = PTHREAD_MUTEX_INITIALIZER;
#ifndef CO_DRIVER_MULTI_INTERFACE
static CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule, int32_t CANbaseAddress);
static CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule, const void *CANptr);
#endif
#ifdef CO_DRIVER_MULTI_INTERFACE
@ -175,7 +179,7 @@ static CO_ReturnError_t setRxFilters(CO_CANmodule_t *CANmodule)
/******************************************************************************/
void CO_CANsetConfigurationMode(void *CANptr)
{
/* Can't do anything because no object is provided */
/* Can't do anything because no reference to CANmodule_t is provided */
}
@ -272,7 +276,7 @@ CO_ReturnError_t CO_CANmodule_init(
rxArray[i].object = NULL;
rxArray[i].CANrx_callback = NULL;
#ifdef CO_DRIVER_MULTI_INTERFACE
rxArray[i].CANbaseAddress = -1;
rxArray[i].CANptr = NULL;
rxArray[i].timestamp.tv_sec = 0;
rxArray[i].timestamp.tv_nsec = 0;
#endif
@ -280,8 +284,7 @@ CO_ReturnError_t CO_CANmodule_init(
#ifndef CO_DRIVER_MULTI_INTERFACE
/* add one interface */
intptr_t CANaddr = (intptr_t)CANptr;
ret = CO_CANmodule_addInterface(CANmodule, (int32_t)CANaddr);
ret = CO_CANmodule_addInterface(CANmodule, CANptr);
if (ret != CO_ERROR_NO) {
CO_CANmodule_disable(CANmodule);
}
@ -298,7 +301,7 @@ static
#endif
CO_ReturnError_t CO_CANmodule_addInterface(
CO_CANmodule_t *CANmodule,
int32_t CANbaseAddress)
const void *CANptr)
{
int32_t ret;
int32_t tmp;
@ -312,7 +315,7 @@ CO_ReturnError_t CO_CANmodule_addInterface(
can_err_mask_t err_mask;
#endif
if (CANmodule->CANnormal) {
if (CANmodule->CANnormal != false) {
/* can't change config now! */
return CO_ERROR_INVALID_STATE;
}
@ -327,8 +330,8 @@ CO_ReturnError_t CO_CANmodule_addInterface(
}
interface = &CANmodule->CANinterfaces[CANmodule->CANinterfaceCount - 1];
interface->CANbaseAddress = CANbaseAddress;
ifName = if_indextoname(CANbaseAddress, interface->ifName);
interface->CANptr = CANptr;
ifName = if_indextoname((uintptr_t)interface->CANptr, interface->ifName);
if (ifName == NULL) {
log_printf(LOG_DEBUG, DBG_ERRNO, "if_indextoname()");
return CO_ERROR_ILLEGAL_ARGUMENT;
@ -376,7 +379,7 @@ CO_ReturnError_t CO_CANmodule_addInterface(
/* bind socket */
memset(&sockAddr, 0, sizeof(sockAddr));
sockAddr.can_family = AF_CAN;
sockAddr.can_ifindex = CANbaseAddress;
sockAddr.can_ifindex = (uintptr_t)interface->CANptr;
ret = bind(interface->fd, (struct sockaddr*)&sockAddr, sizeof(sockAddr));
if(ret < 0){
log_printf(LOG_ERR, CAN_BINDING_FAILED, interface->ifName);
@ -506,7 +509,7 @@ CO_ReturnError_t CO_CANrxBufferInit(
buffer->object = object;
buffer->CANrx_callback = CANrx_callback;
#ifdef CO_DRIVER_MULTI_INTERFACE
buffer->CANbaseAddress = -1;
buffer->CANptr = NULL;
buffer->timestamp.tv_nsec = 0;
buffer->timestamp.tv_sec = 0;
#endif
@ -538,36 +541,35 @@ CO_ReturnError_t CO_CANrxBufferInit(
/******************************************************************************/
bool_t CO_CANrxBuffer_getInterface(
CO_CANmodule_t *CANmodule,
uint32_t ident,
int32_t *CANbaseAddressRx,
uint16_t ident,
const void **const CANptrRx,
struct timespec *timestamp)
{
if (CANmodule != NULL){
uint32_t index;
CO_CANrx_t *buffer;
CO_CANrx_t *buffer;
index = CO_CANgetIndexFromIdent(CANmodule->rxIdentToIndex, ident);
if ((index == CO_INVALID_COB_ID) || (index > CANmodule->rxSize)) {
return false;
}
buffer = &CANmodule->rxArray[index];
/* return values */
if (CANbaseAddressRx != NULL) {
*CANbaseAddressRx = buffer->CANbaseAddress;
}
if (timestamp != NULL) {
*timestamp = buffer->timestamp;
}
if (buffer->CANbaseAddress >= 0) {
return true;
}
else {
return false;
}
if (CANmodule == NULL){
return false;
}
const uint32_t index = CO_CANgetIndexFromIdent(CANmodule->rxIdentToIndex, ident);
if ((index == CO_INVALID_COB_ID) || (index > CANmodule->rxSize)) {
return false;
}
buffer = &CANmodule->rxArray[index];
/* return values */
if (CANptrRx != NULL) {
*CANptrRx = buffer->CANptr;
}
if (timestamp != NULL) {
*timestamp = buffer->timestamp;
}
if (buffer->CANptr != NULL) {
return true;
}
else {
return false;
}
return false;
}
#endif
@ -592,7 +594,7 @@ CO_CANtx_t *CO_CANtxBufferInit(
CO_CANsetIdentToIndex(CANmodule->txIdentToIndex, index, ident, buffer->ident);
#endif
buffer->CANbaseAddress = -1;
buffer->CANptr = NULL;
/* CAN identifier and rtr */
buffer->ident = ident & CAN_SFF_MASK;
@ -612,8 +614,8 @@ CO_CANtx_t *CO_CANtxBufferInit(
/******************************************************************************/
CO_ReturnError_t CO_CANtxBuffer_setInterface(
CO_CANmodule_t *CANmodule,
uint32_t ident,
int32_t CANbaseAddressTx)
uint16_t ident,
const void *CANptrTx)
{
if (CANmodule != NULL) {
uint32_t index;
@ -622,7 +624,7 @@ CO_ReturnError_t CO_CANtxBuffer_setInterface(
if ((index == CO_INVALID_COB_ID) || (index > CANmodule->txSize)) {
return CO_ERROR_PARAMETERS;
}
CANmodule->txArray[index].CANbaseAddress = CANbaseAddressTx;
CANmodule->txArray[index].CANptr = CANptrTx;
return CO_ERROR_NO;
}
@ -743,8 +745,8 @@ CO_ReturnError_t CO_CANCheckSend(CO_CANmodule_t *CANmodule, CO_CANtx_t *buffer)
for (i = 0; i < CANmodule->CANinterfaceCount; i++) {
CO_CANinterface_t *interface = &CANmodule->CANinterfaces[i];
if (buffer->CANbaseAddress < 0 ||
buffer->CANbaseAddress == interface->CANbaseAddress) {
if ((buffer->CANptr == NULL) ||
buffer->CANptr == interface->CANptr) {
CO_ReturnError_t tmp;
@ -890,7 +892,9 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
{
int32_t retval;
int32_t ret;
int32_t CANbaseAddress __attribute__((unused));
#ifdef CO_DRIVER_MULTI_INTERFACE
const void *CANptr;
#endif
CO_ReturnError_t err;
CO_CANinterface_t *interface = NULL;
struct epoll_event ev[1];
@ -949,8 +953,10 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
interface = &CANmodule->CANinterfaces[i];
if (ev[0].data.fd == interface->fd) {
#ifdef CO_DRIVER_MULTI_INTERFACE
/* get interface handle */
CANbaseAddress = interface->CANbaseAddress;
CANdriverState = interface->CANptr;
#endif
/* get message */
err = CO_CANread(CANmodule, interface, &msg, &timestamp);
if (err != CO_ERROR_NO) {
@ -989,7 +995,7 @@ int32_t CO_CANrxWait(CO_CANmodule_t *CANmodule, int fdTimer, CO_CANrxMsg_t *buff
#ifdef CO_DRIVER_MULTI_INTERFACE
/* Store message info */
CANmodule->rxArray[msgIndex].timestamp = timestamp;
CANmodule->rxArray[msgIndex].CANbaseAddress = CANbaseAddress;
CANmodule->rxArray[msgIndex].CANptr = CANptr;
#endif
}
retval = msgIndex;

View file

@ -129,7 +129,6 @@ static inline uint8_t *CO_CANrxMsg_readData(void *rxMsg) {
}
/* Received message object */
typedef struct {
uint32_t ident;
@ -138,7 +137,7 @@ typedef struct {
void (*CANrx_callback)(void *object, void *message);
#ifdef CO_DRIVER_MULTI_INTERFACE
/* info about last received message */
int32_t CANbaseAddress; /* CAN Interface identifier */
const void *CANptr; /* CAN Interface identifier */
struct timespec timestamp; /* time of reception */
#endif
} CO_CANrx_t;
@ -231,12 +230,12 @@ static inline void CO_UNLOCK_OD() {
* Function must be called after CO_CANmodule_init.
*
* @param CANmodule This object will be initialized.
* @param CANbaseAddress CAN module base address.
* @param CANptr CAN module interface index (return value if_nametoindex(), NO pointer!).
* @return #CO_ReturnError_t: CO_ERROR_NO, CO_ERROR_ILLEGAL_ARGUMENT,
* CO_ERROR_SYSCALL or CO_ERROR_INVALID_STATE.
*/
CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule,
int32_t CANbaseAddress);
const void *CANptr);
/*
* Check on which interface the last message for one message buffer was received
@ -246,7 +245,7 @@ CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule,
*
* @param CANmodule This object.
* @param ident 11-bit standard CAN Identifier.
* @param [out] CANbaseAddressRx message was received on this interface
* @param [out] CANptrRx message was received on this interface
* @param [out] timestamp message was received at this time (system clock)
*
* @retval false message has never been received, therefore no base address
@ -254,8 +253,8 @@ CO_ReturnError_t CO_CANmodule_addInterface(CO_CANmodule_t *CANmodule,
* @retval true base address and timestamp are valid
*/
bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule,
uint32_t ident,
int32_t *CANbaseAddressRx,
uint16_t ident,
const void **const CANptrRx,
struct timespec *timestamp);
/*
@ -264,26 +263,26 @@ bool_t CO_CANrxBuffer_getInterface(CO_CANmodule_t *CANmodule,
* It is in the responsibility of the user to ensure that the correct interface
* is used. Some messages need to be transmitted on all interfaces.
*
* If given interface is unknown or "-1" is used, a message is transmitted on
* If given interface is unknown or NULL is used, a message is transmitted on
* all available interfaces.
*
* @param CANmodule This object.
* @param ident 11-bit standard CAN Identifier.
* @param CANbaseAddressTx use this interface. -1 = not specified
* @param CANptrTx use this interface. NULL = not specified
*
* @return #CO_ReturnError_t: CO_ERROR_NO or CO_ERROR_ILLEGAL_ARGUMENT.
*/
CO_ReturnError_t CO_CANtxBuffer_setInterface(CO_CANmodule_t *CANmodule,
uint32_t ident,
int32_t CANbaseAddressTx);
#endif
uint16_t ident,
const void *CANptrTx);
#endif /* CO_DRIVER_MULTI_INTERFACE */
/*
* Functions receives CAN messages. It is blocking.
*
* This function can be used in two ways
* - automatic mode (call callback that is set by CO_CANrxBufferInit() function)
* - automatic mode (call callback that is set by #CO_CANrxBufferInit() function)
* - manual mode (evaluate message filters, return received message)
*
* Both modes can be combined.

View file

@ -32,10 +32,13 @@
#include "301/CO_driver.h"
#include "CO_error.h"
#if defined CO_DRIVER_ERROR_REPORTING && __has_include("syslog/log.h")
#include "syslog/log.h"
#include "msgs.h"
#if defined CO_DRIVER_ERROR_REPORTING
#if __has_include("syslog/log.h")
#include "syslog/log.h"
#include "msgs.h"
#else
#include "CO_msgs.h"
#endif
#else
#define log_printf(macropar_prio, macropar_message, ...)
#endif
@ -192,7 +195,7 @@ void CO_CANerror_init(
}
CANerrorhandler->fd = fd;
CANerrorhandler->ifName = ifName;
memcpy(CANerrorhandler->ifName, ifName, sizeof(CANerrorhandler->ifName));
CANerrorhandler->noackCounter = 0;
CANerrorhandler->listenOnly = false;
CANerrorhandler->timestamp.tv_sec = 0;

View file

@ -71,11 +71,11 @@ typedef enum {
*/
typedef struct {
int fd; /**< interface FD */
const char *ifName; /**< interface name as string */
char ifName[IFNAMSIZ]; /**< interface name as string */
uint32_t noackCounter;
volatile unsigned char listenOnly; /**< set to listen only mode */
volatile bool_t listenOnly; /**< set to listen only mode */
struct timespec timestamp; /**< listen only mode started at this time */
} CO_CANinterfaceErrorhandler_t;

95
socketCAN/CO_msgs.h Normal file
View file

@ -0,0 +1,95 @@
/**
* CAN module object for Linux socketCAN.
*
* This file is a template for other microcontrollers.
*
* @file CO_msgs.h
* @ingroup CO_driver
* @author Martin Wagner
* @copyright 2020 Neuberger Gebaeudeautomation GmbH
*
*
* This file is part of CANopenNode, an opensource CANopen Stack.
* Project home page is <https://github.com/CANopenNode/CANopenNode>.
* For more information on CANopen see <http://www.can-cia.org/>.
*
* 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_MSGS_H
#define CO_MSGS_H
#include <stdio.h>
#include <syslog.h>
#include "CO_msgs.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* message printing function
*/
#define log_printf(macropar_prio, macropar_message, ...) \
if (macropar_prio < LOG_DEBUG) { \
printf(macropar_message, ##__VA_ARGS__); \
}
/*
* message logging function. You need to open the log previous to this.
*/
//#define log_printf(macropar_prio, macropar_message, ...) syslog(macropar_prio, macropar_message, ##__VA_ARGS__);
/*
* Message definitions for Linux CANopen socket driver (notice and errors)
*/
#define CAN_NOT_FOUND "CAN Interface \"%s\" not found"
#define CAN_INIT_FAILED "CAN Interface \"%s\" Init failed"
#define CAN_NAMETOINDEX "Interface \"%s\" -> Index %d"
#define CAN_SOCKET_BUF_SIZE "CAN Interface \"%s\" Buffer set to %d messages (%d Bytes)"
#define CAN_BINDING_FAILED "Binding CAN Interface \"%s\" failed"
#define CAN_ERROR_FILTER_FAILED "Setting CAN Interface \"%s\" error filter failed"
#define CAN_FILTER_FAILED "Setting CAN Interface \"%s\" message filter failed"
#define CAN_RX_SOCKET_QUEUE_OVERFLOW "CAN Interface \"%s\" has lost %d messages"
#define CAN_BUSOFF "CAN Interface \"%s\" changed to \"Bus Off\". Switching to Listen Only mode..."
#define CAN_NOACK "CAN Interface \"%s\" no \"ACK\" received. Switching to Listen Only mode..."
#define CAN_RX_PASSIVE "CAN Interface \"%s\" changed state to \"Rx Passive\""
#define CAN_TX_PASSIVE "CAN Interface \"%s\" changed state to \"Tx Passive\""
#define CAN_TX_LEVEL_ACTIVE "CAN Interface \"%s\" changed state to \"Active\""
#define CAN_RX_BUF_OVERFLOW "CAN Interface \"%s\" Rx buffer overflow. Message dropped"
#define CAN_TX_BUF_OVERFLOW "CAN Interface \"%s\" Tx buffer overflow. Message dropped"
#define CAN_RX_LEVEL_WARNING "CAN Interface \"%s\" reached Rx Warning Level"
#define CAN_TX_LEVEL_WARNING "CAN Interface \"%s\" reached Tx Warning Level"
/*
* Debug
*/
#define DBG_ERRNO "(%s) OS error \"%s\" in %s", __func__, strerror(errno)
#define DBG_CAN_TX_FAILED "(%s) Transmitting CAN msg OID 0x%08x failed(%s)", __func__
#define DBG_CAN_RX_PARAM_FAILED "(%s) Setting CAN rx buffer failed (%s)", __func__
#define DBG_CAN_RX_FAILED "(%s) Receiving CAN msg failed (%s)", __func__
#define DBG_CAN_ERROR_GENERAL "(%s) Socket error msg ID: 0x%08x, Data[0..7]: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x (%s)", __func__
#define DBG_CAN_RX_EPOLL "(%s) CAN Epoll error (0x%02x - %s)", __func__
#define DBG_CAN_SET_LISTEN_ONLY "(%s) %s Set Listen Only", __func__
#define DBG_CAN_CLR_LISTEN_ONLY "(%s) %s Leave Listen Only", __func__
#ifdef __cplusplus
}
#endif /* __cplusplus */
/** @} */
#endif